From e78981bc0ba538f88261946f44e3b8e7c5351b6c Mon Sep 17 00:00:00 2001 From: Guy Eilam Date: Tue, 16 Aug 2011 19:49:12 +0300 Subject: [PATCH] --- yaml --- r: 266050 b: refs/heads/master c: e9eb8cbe77139470651c858b8b7a3d20d332cf47 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 25 +- trunk/drivers/bcma/driver_chipcommon_pmu.c | 20 +- trunk/drivers/bcma/scan.c | 2 +- trunk/drivers/bcma/sprom.c | 15 - trunk/drivers/net/wireless/ath/ath.h | 51 +- trunk/drivers/net/wireless/ath/ath9k/ani.c | 2 +- trunk/drivers/net/wireless/ath/ath9k/ani.h | 5 +- .../net/wireless/ath/ath9k/ar5008_initvals.h | 131 +- .../net/wireless/ath/ath9k/ar9001_initvals.h | 266 +- .../net/wireless/ath/ath9k/ar9002_hw.c | 56 +- .../net/wireless/ath/ath9k/ar9002_initvals.h | 3403 +++++---- .../net/wireless/ath/ath9k/ar9002_mac.c | 2 +- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 2 +- .../net/wireless/ath/ath9k/ar9003_calib.c | 32 +- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- .../net/wireless/ath/ath9k/ar9003_hw.c | 89 +- .../net/wireless/ath/ath9k/ar9003_mac.c | 34 +- .../net/wireless/ath/ath9k/ar9003_paprd.c | 4 +- .../net/wireless/ath/ath9k/ar9003_phy.c | 4 +- .../net/wireless/ath/ath9k/ar9003_phy.h | 2 + .../wireless/ath/ath9k/ar9580_1p0_initvals.h | 1673 ----- trunk/drivers/net/wireless/ath/ath9k/ath9k.h | 16 +- trunk/drivers/net/wireless/ath/ath9k/beacon.c | 6 +- trunk/drivers/net/wireless/ath/ath9k/calib.c | 3 +- trunk/drivers/net/wireless/ath/ath9k/common.c | 26 - trunk/drivers/net/wireless/ath/ath9k/common.h | 1 - trunk/drivers/net/wireless/ath/ath9k/debug.c | 395 +- trunk/drivers/net/wireless/ath/ath9k/debug.h | 47 - .../net/wireless/ath/ath9k/eeprom_4k.c | 5 +- .../net/wireless/ath/ath9k/htc_drv_init.c | 28 +- .../net/wireless/ath/ath9k/htc_drv_main.c | 21 +- trunk/drivers/net/wireless/ath/ath9k/hw-ops.h | 8 +- trunk/drivers/net/wireless/ath/ath9k/hw.c | 43 +- trunk/drivers/net/wireless/ath/ath9k/hw.h | 10 +- trunk/drivers/net/wireless/ath/ath9k/init.c | 70 +- trunk/drivers/net/wireless/ath/ath9k/mac.c | 19 +- trunk/drivers/net/wireless/ath/ath9k/mac.h | 5 +- trunk/drivers/net/wireless/ath/ath9k/main.c | 563 +- trunk/drivers/net/wireless/ath/ath9k/pci.c | 48 +- trunk/drivers/net/wireless/ath/ath9k/rc.c | 34 +- trunk/drivers/net/wireless/ath/ath9k/recv.c | 38 +- trunk/drivers/net/wireless/ath/ath9k/reg.h | 18 +- trunk/drivers/net/wireless/ath/ath9k/xmit.c | 305 +- .../drivers/net/wireless/ath/carl9170/Kconfig | 14 - .../net/wireless/ath/carl9170/carl9170.h | 24 - trunk/drivers/net/wireless/ath/carl9170/cmd.c | 34 - trunk/drivers/net/wireless/ath/carl9170/cmd.h | 1 - trunk/drivers/net/wireless/ath/carl9170/fw.c | 3 - .../drivers/net/wireless/ath/carl9170/fwcmd.h | 11 - .../drivers/net/wireless/ath/carl9170/main.c | 229 +- trunk/drivers/net/wireless/ath/carl9170/phy.c | 16 +- .../net/wireless/ath/carl9170/version.h | 4 +- trunk/drivers/net/wireless/ath/main.c | 8 +- trunk/drivers/net/wireless/b43/Kconfig | 16 +- trunk/drivers/net/wireless/b43/b43.h | 25 +- trunk/drivers/net/wireless/b43/bus.c | 2 - trunk/drivers/net/wireless/b43/dma.c | 157 +- trunk/drivers/net/wireless/b43/dma.h | 16 +- trunk/drivers/net/wireless/b43/main.c | 74 +- trunk/drivers/net/wireless/b43/phy_common.c | 32 - trunk/drivers/net/wireless/b43/phy_common.h | 2 - trunk/drivers/net/wireless/b43/phy_ht.c | 205 - trunk/drivers/net/wireless/b43/phy_ht.h | 19 - trunk/drivers/net/wireless/b43/phy_lcn.c | 443 +- trunk/drivers/net/wireless/b43/phy_lcn.h | 16 +- trunk/drivers/net/wireless/b43/phy_n.c | 575 +- trunk/drivers/net/wireless/b43/phy_n.h | 4 - trunk/drivers/net/wireless/b43/pio.c | 12 +- trunk/drivers/net/wireless/b43/radio_2055.c | 1 - trunk/drivers/net/wireless/b43/radio_2056.c | 2 - trunk/drivers/net/wireless/b43/radio_2056.h | 26 + trunk/drivers/net/wireless/b43/radio_2059.c | 2 - trunk/drivers/net/wireless/b43/tables_nphy.c | 1 - .../drivers/net/wireless/b43/tables_phy_ht.c | 86 - .../drivers/net/wireless/b43/tables_phy_ht.h | 4 - .../drivers/net/wireless/b43/tables_phy_lcn.c | 673 -- .../drivers/net/wireless/b43/tables_phy_lcn.h | 18 - trunk/drivers/net/wireless/b43/xmit.c | 120 +- trunk/drivers/net/wireless/b43/xmit.h | 62 +- .../net/wireless/b43legacy/b43legacy.h | 4 + trunk/drivers/net/wireless/b43legacy/main.c | 4 +- trunk/drivers/net/wireless/iwlwifi/iwl-1000.c | 42 +- trunk/drivers/net/wireless/iwlwifi/iwl-2000.c | 52 +- trunk/drivers/net/wireless/iwlwifi/iwl-5000.c | 72 +- trunk/drivers/net/wireless/iwlwifi/iwl-6000.c | 60 +- .../net/wireless/iwlwifi/iwl-agn-calib.c | 43 +- .../net/wireless/iwlwifi/iwl-agn-eeprom.c | 6 +- .../drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 13 + .../net/wireless/iwlwifi/iwl-agn-lib.c | 678 +- .../drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 93 +- .../net/wireless/iwlwifi/iwl-agn-rxon.c | 69 +- .../net/wireless/iwlwifi/iwl-agn-sta.c | 84 +- .../drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 68 +- .../drivers/net/wireless/iwlwifi/iwl-agn-tt.h | 1 + .../drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 913 +-- .../net/wireless/iwlwifi/iwl-agn-ucode.c | 57 +- trunk/drivers/net/wireless/iwlwifi/iwl-agn.c | 948 ++- trunk/drivers/net/wireless/iwlwifi/iwl-agn.h | 65 +- trunk/drivers/net/wireless/iwlwifi/iwl-bus.h | 34 +- .../net/wireless/iwlwifi/iwl-commands.h | 13 +- trunk/drivers/net/wireless/iwlwifi/iwl-core.c | 295 +- trunk/drivers/net/wireless/iwlwifi/iwl-core.h | 140 +- trunk/drivers/net/wireless/iwlwifi/iwl-csr.h | 18 - .../drivers/net/wireless/iwlwifi/iwl-debug.h | 40 +- .../net/wireless/iwlwifi/iwl-debugfs.c | 343 +- trunk/drivers/net/wireless/iwlwifi/iwl-dev.h | 519 +- .../net/wireless/iwlwifi/iwl-devtrace.h | 2 - .../drivers/net/wireless/iwlwifi/iwl-eeprom.c | 62 +- .../drivers/net/wireless/iwlwifi/iwl-eeprom.h | 1 + trunk/drivers/net/wireless/iwlwifi/iwl-fh.h | 20 +- .../net/wireless/iwlwifi/iwl-helpers.h | 114 +- trunk/drivers/net/wireless/iwlwifi/iwl-io.c | 192 +- trunk/drivers/net/wireless/iwlwifi/iwl-io.h | 61 +- trunk/drivers/net/wireless/iwlwifi/iwl-led.c | 11 +- trunk/drivers/net/wireless/iwlwifi/iwl-pci.c | 53 +- trunk/drivers/net/wireless/iwlwifi/iwl-pci.h | 116 - .../drivers/net/wireless/iwlwifi/iwl-power.c | 19 +- trunk/drivers/net/wireless/iwlwifi/iwl-prph.h | 4 +- trunk/drivers/net/wireless/iwlwifi/iwl-rx.c | 125 +- trunk/drivers/net/wireless/iwlwifi/iwl-scan.c | 97 +- .../drivers/net/wireless/iwlwifi/iwl-shared.h | 482 -- trunk/drivers/net/wireless/iwlwifi/iwl-sta.c | 110 +- trunk/drivers/net/wireless/iwlwifi/iwl-sta.h | 4 +- .../net/wireless/iwlwifi/iwl-sv-open.c | 22 +- .../net/wireless/iwlwifi/iwl-trans-int-pcie.h | 424 +- .../net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 859 +-- .../net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 622 +- .../drivers/net/wireless/iwlwifi/iwl-trans.c | 1529 +--- .../drivers/net/wireless/iwlwifi/iwl-trans.h | 280 +- trunk/drivers/net/wireless/libertas/README | 25 + trunk/drivers/net/wireless/libertas/dev.h | 4 +- trunk/drivers/net/wireless/libertas/if_usb.c | 21 - trunk/drivers/net/wireless/mwifiex/cfg80211.c | 207 +- trunk/drivers/net/wireless/mwifiex/fw.h | 15 +- trunk/drivers/net/wireless/mwifiex/init.c | 21 + trunk/drivers/net/wireless/mwifiex/join.c | 35 +- trunk/drivers/net/wireless/mwifiex/main.h | 49 +- trunk/drivers/net/wireless/mwifiex/scan.c | 1578 +++- .../drivers/net/wireless/mwifiex/sta_event.c | 5 + .../drivers/net/wireless/mwifiex/sta_ioctl.c | 201 +- trunk/drivers/net/wireless/mwl8k.c | 11 +- trunk/drivers/net/wireless/p54/eeprom.c | 26 +- trunk/drivers/net/wireless/p54/fwio.c | 2 - trunk/drivers/net/wireless/p54/main.c | 113 +- trunk/drivers/net/wireless/p54/p54.h | 18 - trunk/drivers/net/wireless/p54/p54spi.c | 2 +- trunk/drivers/net/wireless/p54/txrx.c | 70 - trunk/drivers/net/wireless/rt2x00/rt2800.h | 3 - trunk/drivers/net/wireless/rt2x00/rt2800lib.c | 191 +- trunk/drivers/net/wireless/rt2x00/rt2800lib.h | 5 +- trunk/drivers/net/wireless/rt2x00/rt2800pci.c | 15 +- trunk/drivers/net/wireless/rt2x00/rt2800usb.c | 7 +- trunk/drivers/net/wireless/rt2x00/rt2x00.h | 30 - trunk/drivers/net/wireless/rt2x00/rt2x00dev.c | 21 - trunk/drivers/net/wireless/rt2x00/rt2x00mac.c | 50 +- .../drivers/net/wireless/rt2x00/rt2x00queue.c | 7 +- .../drivers/net/wireless/rt2x00/rt2x00queue.h | 5 +- trunk/drivers/net/wireless/rtlwifi/base.c | 161 - trunk/drivers/net/wireless/rtlwifi/base.h | 2 - trunk/drivers/net/wireless/rtlwifi/debug.c | 6 +- .../net/wireless/rtlwifi/rtl8192ce/def.h | 139 + .../net/wireless/rtlwifi/rtl8192ce/sw.c | 30 +- .../net/wireless/rtlwifi/rtl8192ce/trx.c | 116 +- .../net/wireless/rtlwifi/rtl8192ce/trx.h | 8 +- .../net/wireless/rtlwifi/rtl8192cu/mac.c | 4 +- .../net/wireless/rtlwifi/rtl8192cu/mac.h | 8 +- .../net/wireless/rtlwifi/rtl8192cu/rf.c | 2 +- .../net/wireless/rtlwifi/rtl8192cu/sw.c | 28 +- .../net/wireless/rtlwifi/rtl8192cu/trx.c | 23 +- .../net/wireless/rtlwifi/rtl8192de/def.h | 35 + .../net/wireless/rtlwifi/rtl8192de/sw.c | 30 +- .../net/wireless/rtlwifi/rtl8192de/trx.c | 121 +- .../net/wireless/rtlwifi/rtl8192de/trx.h | 8 +- .../net/wireless/rtlwifi/rtl8192se/def.h | 39 +- .../net/wireless/rtlwifi/rtl8192se/sw.c | 30 +- .../net/wireless/rtlwifi/rtl8192se/trx.c | 124 +- trunk/drivers/net/wireless/rtlwifi/wifi.h | 35 - trunk/drivers/net/wireless/wl12xx/main.c | 13 + trunk/drivers/net/wireless/wl12xx/sdio_test.c | 2 +- trunk/drivers/net/wireless/wl12xx/tx.c | 8 +- trunk/drivers/net/wireless/wl12xx/tx.h | 1 + trunk/drivers/net/wireless/wl12xx/wl12xx.h | 3 + trunk/drivers/nfc/pn533.c | 17 +- trunk/drivers/ssb/main.c | 24 +- trunk/drivers/staging/Kconfig | 2 + trunk/drivers/staging/Makefile | 1 + trunk/drivers/staging/ath6kl/Kconfig | 158 + trunk/drivers/staging/ath6kl/Makefile | 122 + trunk/drivers/staging/ath6kl/TODO | 25 + .../staging/ath6kl/bmi/include/bmi_internal.h | 54 + trunk/drivers/staging/ath6kl/bmi/src/bmi.c | 1010 +++ .../ath6kl/hif/common/hif_sdio_common.h | 87 + .../sdio/linux_sdio/include/hif_internal.h | 131 + .../ath6kl/hif/sdio/linux_sdio/src/hif.c | 1273 ++++ .../hif/sdio/linux_sdio/src/hif_scatter.c | 393 + .../drivers/staging/ath6kl/htc2/AR6000/ar6k.c | 1479 ++++ .../drivers/staging/ath6kl/htc2/AR6000/ar6k.h | 401 + .../staging/ath6kl/htc2/AR6000/ar6k_events.c | 783 ++ .../staging/ath6kl/htc2/AR6000/ar6k_gmbox.c | 755 ++ .../ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c | 1284 ++++ trunk/drivers/staging/ath6kl/htc2/htc.c | 575 ++ trunk/drivers/staging/ath6kl/htc2/htc_debug.h | 38 + .../staging/ath6kl/htc2/htc_internal.h | 211 + trunk/drivers/staging/ath6kl/htc2/htc_recv.c | 1572 ++++ trunk/drivers/staging/ath6kl/htc2/htc_send.c | 1018 +++ .../staging/ath6kl/htc2/htc_services.c | 450 ++ .../drivers/staging/ath6kl/include/a_config.h | 31 + .../drivers/staging/ath6kl/include/a_debug.h | 195 + trunk/drivers/staging/ath6kl/include/a_drv.h | 32 + .../staging/ath6kl/include/a_drv_api.h | 204 + .../drivers/staging/ath6kl/include/a_osapi.h | 32 + .../staging/ath6kl/include/aggr_recv_api.h | 140 + .../staging/ath6kl/include/ar3kconfig.h | 65 + .../staging/ath6kl/include/ar6000_api.h | 32 + .../staging/ath6kl/include/ar6000_diag.h | 48 + .../staging/ath6kl/include/ar6kap_common.h | 44 + .../staging/ath6kl/include/athbtfilter.h | 135 + trunk/drivers/staging/ath6kl/include/bmi.h | 134 + .../include/common/AR6002/AR6K_version.h | 52 + .../ath6kl/include/common/AR6002/addrs.h | 90 + .../AR6002/hw4.0/hw/apb_athr_wlan_map.h | 40 + .../include/common/AR6002/hw4.0/hw/apb_map.h | 40 + .../common/AR6002/hw4.0/hw/mbox_host_reg.h | 24 + .../include/common/AR6002/hw4.0/hw/mbox_reg.h | 552 ++ .../AR6002/hw4.0/hw/mbox_wlan_host_reg.h | 471 ++ .../common/AR6002/hw4.0/hw/mbox_wlan_reg.h | 589 ++ .../include/common/AR6002/hw4.0/hw/rtc_reg.h | 187 + .../common/AR6002/hw4.0/hw/rtc_wlan_reg.h | 162 + .../include/common/AR6002/hw4.0/hw/uart_reg.h | 40 + .../staging/ath6kl/include/common/athdefs.h | 75 + .../staging/ath6kl/include/common/bmi_msg.h | 233 + .../staging/ath6kl/include/common/cnxmgmt.h | 36 + .../staging/ath6kl/include/common/dbglog.h | 126 + .../staging/ath6kl/include/common/dbglog_id.h | 558 ++ .../staging/ath6kl/include/common/discovery.h | 75 + .../ath6kl/include/common/epping_test.h | 111 + .../staging/ath6kl/include/common/gmboxif.h | 70 + .../staging/ath6kl/include/common/gpio_reg.h | 9 + .../staging/ath6kl/include/common/htc.h | 227 + .../ath6kl/include/common/htc_services.h | 52 + .../staging/ath6kl/include/common/pkt_log.h | 45 + .../staging/ath6kl/include/common/roaming.h | 41 + .../staging/ath6kl/include/common/targaddrs.h | 395 + .../staging/ath6kl/include/common/testcmd.h | 185 + .../staging/ath6kl/include/common/tlpm.h | 38 + .../staging/ath6kl/include/common/wlan_defs.h | 79 + .../staging/ath6kl/include/common/wmi.h | 3220 ++++++++ .../staging/ath6kl/include/common/wmix.h | 271 + .../staging/ath6kl/include/common_drv.h | 104 + .../staging/ath6kl/include/dbglog_api.h | 52 + .../drivers/staging/ath6kl/include/dl_list.h | 153 + .../drivers/staging/ath6kl/include/dset_api.h | 65 + .../ath6kl/include/hci_transport_api.h | 259 + trunk/drivers/staging/ath6kl/include/hif.h | 456 ++ .../staging/ath6kl/include/host_version.h | 52 + .../drivers/staging/ath6kl/include/htc_api.h | 575 ++ .../staging/ath6kl/include/htc_packet.h | 227 + .../drivers/staging/ath6kl/include/wlan_api.h | 128 + .../drivers/staging/ath6kl/include/wmi_api.h | 441 ++ .../staging/ath6kl/miscdrv/ar3kconfig.c | 565 ++ .../ath6kl/miscdrv/ar3kps/ar3kpsconfig.c | 572 ++ .../ath6kl/miscdrv/ar3kps/ar3kpsconfig.h | 75 + .../ath6kl/miscdrv/ar3kps/ar3kpsparser.c | 969 +++ .../ath6kl/miscdrv/ar3kps/ar3kpsparser.h | 113 + .../staging/ath6kl/miscdrv/common_drv.c | 910 +++ .../staging/ath6kl/miscdrv/credit_dist.c | 417 ++ .../drivers/staging/ath6kl/miscdrv/miscdrv.h | 42 + .../staging/ath6kl/os/linux/ar6000_drv.c | 6267 ++++++++++++++++ .../staging/ath6kl/os/linux/ar6000_pm.c | 626 ++ .../staging/ath6kl/os/linux/ar6000_raw_if.c | 455 ++ .../staging/ath6kl/os/linux/cfg80211.c | 1892 +++++ .../ath6kl/os/linux/export_hci_transport.c | 124 + .../staging/ath6kl/os/linux/hci_bridge.c | 1141 +++ .../ath6kl/os/linux/include/ar6000_drv.h | 776 ++ .../ath6kl/os/linux/include/ar6k_pal.h | 36 + .../ath6kl/os/linux/include/ar6xapi_linux.h | 190 + .../ath6kl/os/linux/include/athdrv_linux.h | 1217 ++++ .../ath6kl/os/linux/include/cfg80211.h | 61 + .../ath6kl/os/linux/include/config_linux.h | 51 + .../ath6kl/os/linux/include/debug_linux.h | 50 + .../os/linux/include/export_hci_transport.h | 76 + .../ath6kl/os/linux/include/ieee80211_ioctl.h | 177 + .../ath6kl/os/linux/include/osapi_linux.h | 339 + .../ath6kl/os/linux/include/wlan_config.h | 108 + .../os/linux/include/wmi_filter_linux.h | 300 + .../drivers/staging/ath6kl/os/linux/netbuf.c | 231 + .../staging/ath6kl/reorder/aggr_rx_internal.h | 117 + .../drivers/staging/ath6kl/reorder/rcv_aggr.c | 661 ++ .../staging/ath6kl/wlan/include/ieee80211.h | 397 + .../ath6kl/wlan/include/ieee80211_node.h | 93 + .../staging/ath6kl/wlan/src/wlan_node.c | 636 ++ .../ath6kl/wlan/src/wlan_recv_beacon.c | 199 + .../staging/ath6kl/wlan/src/wlan_utils.c | 58 + trunk/drivers/staging/ath6kl/wmi/wmi.c | 6444 +++++++++++++++++ trunk/drivers/staging/ath6kl/wmi/wmi_host.h | 102 + .../linux/bcma/bcma_driver_chipcommon.h | 18 - trunk/include/linux/ieee80211.h | 61 +- trunk/include/linux/nfc.h | 2 - trunk/include/linux/nl80211.h | 144 +- trunk/include/linux/ssb/ssb.h | 2 +- trunk/include/net/cfg80211.h | 186 +- trunk/include/net/mac80211.h | 28 - trunk/include/net/nfc.h | 7 +- trunk/include/net/regulatory.h | 16 +- trunk/net/mac80211/Kconfig | 13 - trunk/net/mac80211/agg-rx.c | 19 +- trunk/net/mac80211/agg-tx.c | 44 +- trunk/net/mac80211/cfg.c | 40 +- trunk/net/mac80211/debugfs.c | 19 +- trunk/net/mac80211/debugfs_netdev.c | 11 +- trunk/net/mac80211/ht.c | 6 +- trunk/net/mac80211/ieee80211_i.h | 67 +- trunk/net/mac80211/iface.c | 6 - trunk/net/mac80211/mesh.c | 267 +- trunk/net/mac80211/mesh.h | 42 +- trunk/net/mac80211/mesh_hwmp.c | 161 +- trunk/net/mac80211/mesh_pathtbl.c | 477 +- trunk/net/mac80211/mesh_plink.c | 243 +- trunk/net/mac80211/mlme.c | 87 +- trunk/net/mac80211/rc80211_minstrel_ht.c | 3 +- trunk/net/mac80211/rx.c | 83 +- trunk/net/mac80211/spectmgmt.c | 6 +- trunk/net/mac80211/sta_info.c | 340 +- trunk/net/mac80211/sta_info.h | 35 +- trunk/net/mac80211/status.c | 55 +- trunk/net/mac80211/tx.c | 40 +- trunk/net/mac80211/util.c | 180 +- trunk/net/mac80211/wme.c | 16 +- trunk/net/mac80211/wme.h | 3 +- trunk/net/mac80211/work.c | 6 +- trunk/net/nfc/core.c | 6 +- trunk/net/nfc/rawsock.c | 13 +- trunk/net/rfkill/rfkill-regulator.c | 1 + trunk/net/wireless/core.c | 2 +- trunk/net/wireless/core.h | 2 + trunk/net/wireless/lib80211_crypt_ccmp.c | 2 + trunk/net/wireless/lib80211_crypt_tkip.c | 4 + trunk/net/wireless/lib80211_crypt_wep.c | 4 + trunk/net/wireless/mesh.c | 3 - trunk/net/wireless/nl80211.c | 191 +- trunk/net/wireless/reg.c | 33 +- trunk/net/wireless/reg.h | 2 - trunk/net/wireless/util.c | 173 +- 344 files changed, 60987 insertions(+), 16293 deletions(-) delete mode 100644 trunk/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h delete mode 100644 trunk/drivers/net/wireless/iwlwifi/iwl-pci.h delete mode 100644 trunk/drivers/net/wireless/iwlwifi/iwl-shared.h create mode 100644 trunk/drivers/staging/ath6kl/Kconfig create mode 100644 trunk/drivers/staging/ath6kl/Makefile create mode 100644 trunk/drivers/staging/ath6kl/TODO create mode 100644 trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h create mode 100644 trunk/drivers/staging/ath6kl/bmi/src/bmi.c create mode 100644 trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_debug.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_internal.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_recv.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_send.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_services.c create mode 100644 trunk/drivers/staging/ath6kl/include/a_config.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_debug.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_drv.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_drv_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_osapi.h create mode 100644 trunk/drivers/staging/ath6kl/include/aggr_recv_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar3kconfig.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6000_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6000_diag.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6kap_common.h create mode 100644 trunk/drivers/staging/ath6kl/include/athbtfilter.h create mode 100644 trunk/drivers/staging/ath6kl/include/bmi.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/athdefs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/bmi_msg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/dbglog.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/dbglog_id.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/discovery.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/epping_test.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/gmboxif.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/gpio_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/htc.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/htc_services.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/pkt_log.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/roaming.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/targaddrs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/testcmd.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/tlpm.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wlan_defs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wmi.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wmix.h create mode 100644 trunk/drivers/staging/ath6kl/include/common_drv.h create mode 100644 trunk/drivers/staging/ath6kl/include/dbglog_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/dl_list.h create mode 100644 trunk/drivers/staging/ath6kl/include/dset_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/hci_transport_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/hif.h create mode 100644 trunk/drivers/staging/ath6kl/include/host_version.h create mode 100644 trunk/drivers/staging/ath6kl/include/htc_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/htc_packet.h create mode 100644 trunk/drivers/staging/ath6kl/include/wlan_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/wmi_api.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/common_drv.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/cfg80211.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/netbuf.c create mode 100644 trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h create mode 100644 trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h create mode 100644 trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c create mode 100644 trunk/drivers/staging/ath6kl/wmi/wmi.c create mode 100644 trunk/drivers/staging/ath6kl/wmi/wmi_host.h diff --git a/[refs] b/[refs] index ba985f0ee58b..b5f86eef69c2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 55768fa6d9462c18c1ce3c862db3bf55bac3b1c7 +refs/heads/master: e9eb8cbe77139470651c858b8b7a3d20d332cf47 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index c66c093978d7..1d2e79db0f58 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1230,7 +1230,7 @@ F: Documentation/aoe/ F: drivers/block/aoe/ ATHEROS ATH GENERIC UTILITIES -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/ath/* @@ -1238,7 +1238,7 @@ F: drivers/net/wireless/ath/* ATHEROS ATH5K WIRELESS DRIVER M: Jiri Slaby M: Nick Kossifidis -M: "Luis R. Rodriguez" +M: "Luis R. Rodriguez" M: Bob Copeland L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org @@ -1247,10 +1247,10 @@ S: Maintained F: drivers/net/wireless/ath/ath5k/ ATHEROS ATH9K WIRELESS DRIVER -M: "Luis R. Rodriguez" -M: Jouni Malinen -M: Vasanthakumar Thiagarajan -M: Senthil Balasubramanian +M: "Luis R. Rodriguez" +M: Jouni Malinen +M: Vasanthakumar Thiagarajan +M: Senthil Balasubramanian L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org W: http://wireless.kernel.org/en/users/Drivers/ath9k @@ -1278,7 +1278,7 @@ F: drivers/input/misc/ati_remote2.c ATLX ETHERNET DRIVERS M: Jay Cliburn M: Chris Snook -M: Jie Yang +M: Jie Yang L: netdev@vger.kernel.org W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net @@ -4492,17 +4492,6 @@ W: http://www.qlogic.com S: Supported F: drivers/net/netxen/ -NFC SUBSYSTEM -M: Lauro Ramos Venancio -M: Aloisio Almeida Jr -M: Samuel Ortiz -L: linux-wireless@vger.kernel.org -S: Maintained -F: net/nfc/ -F: include/linux/nfc.h -F: include/net/nfc.h -F: drivers/nfc/ - NFS, SUNRPC, AND LOCKD CLIENTS M: Trond Myklebust L: linux-nfs@vger.kernel.org diff --git a/trunk/drivers/bcma/driver_chipcommon_pmu.c b/trunk/drivers/bcma/driver_chipcommon_pmu.c index 4bc10aa57bd4..5940c81e7e12 100644 --- a/trunk/drivers/bcma/driver_chipcommon_pmu.c +++ b/trunk/drivers/bcma/driver_chipcommon_pmu.c @@ -90,24 +90,6 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) } } -/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ -void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) -{ - struct bcma_bus *bus = cc->core->bus; - u32 val; - - val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); - if (enable) { - val |= BCMA_CHIPCTL_4331_EXTPA_EN; - if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) - val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; - } else { - val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; - val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; - } - bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); -} - void bcma_pmu_workarounds(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -117,7 +99,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ + pr_err("Enabling Ext PA lines not implemented\n"); break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/trunk/drivers/bcma/scan.c b/trunk/drivers/bcma/scan.c index cad994857683..0ea390f9aa9e 100644 --- a/trunk/drivers/bcma/scan.c +++ b/trunk/drivers/bcma/scan.c @@ -281,7 +281,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, /* get & parse master ports */ for (i = 0; i < ports[0]; i++) { - s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); + u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); if (mst_port_d < 0) return -EILSEQ; } diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index d7292390d236..8b5b7856abe3 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -133,15 +133,6 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); } - - bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)]; - - bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)]; - bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)]; - bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)]; - bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)]; - - bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)]; } int bcma_sprom_get(struct bcma_bus *bus) @@ -161,9 +152,6 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == 0x4331) - bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); - /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). * According to brcm80211 this applies to cards with PCIe rev >= 6 * TODO: understand this condition and use it */ @@ -171,9 +159,6 @@ int bcma_sprom_get(struct bcma_bus *bus) BCMA_CC_SPROM_PCIE6; bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == 0x4331) - bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); - err = bcma_sprom_valid(sprom); if (err) goto out; diff --git a/trunk/drivers/net/wireless/ath/ath.h b/trunk/drivers/net/wireless/ath/ath.h index 4ed7f248a577..17c4b56c3874 100644 --- a/trunk/drivers/net/wireless/ath/ath.h +++ b/trunk/drivers/net/wireless/ath/ath.h @@ -140,6 +140,9 @@ struct ath_common { u8 curbssid[ETH_ALEN]; u8 bssidmask[ETH_ALEN]; + u8 tx_chainmask; + u8 rx_chainmask; + u32 rx_bufsize; u32 keymax; @@ -175,29 +178,23 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); -extern __attribute__((format (printf, 2, 3))) -void ath_printk(const char *level, const char *fmt, ...); - -#define _ath_printk(level, common, fmt, ...) \ -do { \ - __always_unused struct ath_common *unused = common; \ - ath_printk(level, fmt, ##__VA_ARGS__); \ -} while (0) +extern __attribute__ ((format (printf, 3, 4))) int +ath_printk(const char *level, struct ath_common *common, const char *fmt, ...); #define ath_emerg(common, fmt, ...) \ - _ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) #define ath_alert(common, fmt, ...) \ - _ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) #define ath_crit(common, fmt, ...) \ - _ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) #define ath_err(common, fmt, ...) \ - _ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) #define ath_warn(common, fmt, ...) \ - _ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) #define ath_notice(common, fmt, ...) \ - _ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) #define ath_info(common, fmt, ...) \ - _ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) /** * enum ath_debug_level - atheros wireless debug level @@ -249,21 +246,27 @@ enum ATH_DEBUG { #ifdef CONFIG_ATH_DEBUG -#define ath_dbg(common, dbg_mask, fmt, ...) \ -do { \ - if ((common)->debug_mask & dbg_mask) \ - _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ -} while (0) - +#define ath_dbg(common, dbg_mask, fmt, ...) \ +({ \ + int rtn; \ + if ((common)->debug_mask & dbg_mask) \ + rtn = ath_printk(KERN_DEBUG, common, fmt, \ + ##__VA_ARGS__); \ + else \ + rtn = 0; \ + \ + rtn; \ +}) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) #else -static inline __attribute__((format (printf, 3, 4))) -void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, - const char *fmt, ...) +static inline __attribute__ ((format (printf, 3, 4))) int +ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, + const char *fmt, ...) { + return 0; } #define ATH_DBG_WARN(foo, arg...) do {} while (0) #define ATH_DBG_WARN_ON_ONCE(foo) ({ \ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ani.c b/trunk/drivers/net/wireless/ath/ath9k/ani.c index d969a11e3425..bfb6481f01f9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ani.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ani.c @@ -643,7 +643,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) listenTime = ath_hw_get_listen_time(common); if (listenTime <= 0) { - ah->stats.ast_ani_lneg_or_lzero++; + ah->stats.ast_ani_lneg++; ath9k_ani_restart(ah); return false; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ani.h b/trunk/drivers/net/wireless/ath/ath9k/ani.h index a547005572e7..dbab5b9ce494 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ani.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ani.h @@ -148,7 +148,8 @@ struct ar5416Stats { u32 ast_ani_ofdmerrs; u32 ast_ani_cckerrs; u32 ast_ani_reset; - u32 ast_ani_lneg_or_lzero; + u32 ast_ani_lzero; + u32 ast_ani_lneg; u32 avgbrssi; struct ath9k_mib_stats ast_mibstats; }; @@ -158,5 +159,7 @@ void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); +int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, + struct ath9k_channel *chan); #endif /* ANI_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index f81e7fc60a36..234617c948a1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -14,71 +14,70 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -static const u32 ar5416Modes[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0}, - {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de}, - {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, - {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18}, - {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190}, - {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134}, - {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b}, - {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, - {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80}, - {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80}, - {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80}, - {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120}, - {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00}, - {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, - {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788}, - {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120}, - {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120}, - {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa}, - {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, - {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402}, - {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06}, - {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b}, - {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b}, - {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a}, - {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf}, - {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f}, - {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f}, - {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f}, - {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000}, - {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +static const u32 ar5416Modes[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0}, + {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de}, + {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, + {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18}, + {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190}, + {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134}, + {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b}, + {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, + {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, + {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, + {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80}, + {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120}, + {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00}, + {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, + {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, + {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c}, + {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, + {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, + {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, + {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, + {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, + {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, + {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, + {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, + {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, + {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, + {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, + {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, + {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, + {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, + {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, + {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; static const u32 ar5416Common[][2] = { @@ -669,6 +668,6 @@ static const u32 ar5416Addac[][2] = { {0x0000989c, 0x00000000}, {0x0000989c, 0x00000000}, {0x0000989c, 0x00000000}, - {0x000098c4, 0x00000000}, + {0x000098cc, 0x00000000}, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index e8bdc75405f1..6d2e2f3303f9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -14,74 +14,73 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -static const u32 ar5416Modes_9100[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2}, - {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, - {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20}, - {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, - {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204}, - {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020}, - {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e}, - {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff}, - {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, - {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, - {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, - {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, - {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00}, - {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, - {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788}, - {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa}, - {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, - {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402}, - {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06}, - {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b}, - {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b}, - {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a}, - {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf}, - {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f}, - {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f}, - {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f}, - {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000}, - {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +static const u32 ar5416Modes_9100[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2}, + {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, + {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18}, + {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, + {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204}, + {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020}, + {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e}, + {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff}, + {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, + {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, + {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0}, + {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, + {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00}, + {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, + {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, + {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, + {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, + {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, + {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, + {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, + {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, + {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, + {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, + {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, + {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, + {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, + {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, + {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, + {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, + {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, + {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, + {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; static const u32 ar5416Common_9100[][2] = { @@ -667,72 +666,71 @@ static const u32 ar5416Addac_9100[][2] = { {0x000098cc, 0x00000000}, }; -static const u32 ar5416Modes_9160[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68}, - {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2}, - {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, - {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20}, - {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, - {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, - {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, - {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, - {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, - {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, - {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00}, - {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, - {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788}, - {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa}, - {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, - {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402}, - {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06}, - {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b}, - {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b}, - {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a}, - {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf}, - {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f}, - {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f}, - {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f}, - {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000}, - {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +static const u32 ar5416Modes_9160[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68}, + {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2}, + {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e}, + {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18}, + {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0}, + {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020}, + {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, + {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, + {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40}, + {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120}, + {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce}, + {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00}, + {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be}, + {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, + {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329}, + {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, + {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, + {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880}, + {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788}, + {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa}, + {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000}, + {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402}, + {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06}, + {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b}, + {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b}, + {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a}, + {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf}, + {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f}, + {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f}, + {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f}, + {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; static const u32 ar5416Common_9160[][2] = { diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 626d547d2f06..44d9d8d56490 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -30,7 +30,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, - ARRAY_SIZE(ar9271Modes_9271), 5); + ARRAY_SIZE(ar9271Modes_9271), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, ARRAY_SIZE(ar9271Common_9271), 2); INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, @@ -41,21 +41,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, ar9271Modes_9271_1_0_only, - ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5); + ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, - ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5); + ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, ar9271Modes_high_power_tx_gain_9271, - ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5); + ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, ar9271Modes_normal_power_tx_gain_9271, - ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5); + ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); return; } if (AR_SREV_9287_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, - ARRAY_SIZE(ar9287Modes_9287_1_1), 5); + ARRAY_SIZE(ar9287Modes_9287_1_1), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, ARRAY_SIZE(ar9287Common_9287_1_1), 2); if (ah->config.pcie_clock_req) @@ -71,7 +71,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, - ARRAY_SIZE(ar9285Modes_9285_1_2), 5); + ARRAY_SIZE(ar9285Modes_9285_1_2), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, ARRAY_SIZE(ar9285Common_9285_1_2), 2); @@ -87,7 +87,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) } } else if (AR_SREV_9280_20_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, - ARRAY_SIZE(ar9280Modes_9280_2), 5); + ARRAY_SIZE(ar9280Modes_9280_2), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, ARRAY_SIZE(ar9280Common_9280_2), 2); @@ -105,7 +105,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); } else if (AR_SREV_9160_10_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, - ARRAY_SIZE(ar5416Modes_9160), 5); + ARRAY_SIZE(ar5416Modes_9160), 6); INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, ARRAY_SIZE(ar5416Common_9160), 2); INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, @@ -134,7 +134,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) } } else if (AR_SREV_9100_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, - ARRAY_SIZE(ar5416Modes_9100), 5); + ARRAY_SIZE(ar5416Modes_9100), 6); INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, ARRAY_SIZE(ar5416Common_9100), 2); INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, @@ -157,7 +157,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) ARRAY_SIZE(ar5416Addac_9100), 2); } else { INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, - ARRAY_SIZE(ar5416Modes), 5); + ARRAY_SIZE(ar5416Modes), 6); INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, ARRAY_SIZE(ar5416Common), 2); INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, @@ -207,19 +207,19 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9280Modes_backoff_13db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9280Modes_backoff_23db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); } else { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); } } @@ -234,15 +234,15 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah) if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9280Modes_high_power_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); } else { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5); + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); } } @@ -251,14 +251,14 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) if (AR_SREV_9287_11_OR_LATER(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9287Modes_rx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5); + ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); else if (AR_SREV_9280_20(ah)) ar9280_20_hw_init_rxgain_ini(ah); if (AR_SREV_9287_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9287Modes_tx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5); + ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); } else if (AR_SREV_9280_20(ah)) { ar9280_20_hw_init_txgain_ini(ah); } else if (AR_SREV_9285_12_OR_LATER(ah)) { @@ -270,24 +270,24 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9285Modes_XE2_0_high_power, ARRAY_SIZE( - ar9285Modes_XE2_0_high_power), 5); + ar9285Modes_XE2_0_high_power), 6); } else { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9285Modes_high_power_tx_gain_9285_1_2, ARRAY_SIZE( - ar9285Modes_high_power_tx_gain_9285_1_2), 5); + ar9285Modes_high_power_tx_gain_9285_1_2), 6); } } else { if (AR_SREV_9285E_20(ah)) { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9285Modes_XE2_0_normal_power, ARRAY_SIZE( - ar9285Modes_XE2_0_normal_power), 5); + ar9285Modes_XE2_0_normal_power), 6); } else { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9285Modes_original_tx_gain_9285_1_2, ARRAY_SIZE( - ar9285Modes_original_tx_gain_9285_1_2), 5); + ar9285Modes_original_tx_gain_9285_1_2), 6); } } } @@ -303,13 +303,17 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) * register as the other analog registers. Hence the 9 writes. */ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, - bool power_off) + int restore, + int power_off) { u8 i; u32 val; + if (ah->is_pciexpress != true || ah->aspm_enabled != true) + return; + /* Nothing to do on restore for 11N */ - if (!power_off /* !restore */) { + if (!restore) { if (AR_SREV_9280_20_OR_LATER(ah)) { /* * AR9280 2.0 or later chips use SerDes values from the diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 863db321070d..7573257731b6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -14,54 +14,53 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -static const u32 ar9280Modes_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20}, - {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b}, - {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010}, - {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, - {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, - {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210}, - {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c}, - {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444}, - {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019}, - {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000}, - {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e}, - {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000}, - {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000}, +static const u32 ar9280Modes_9280_2[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2}, + {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18}, + {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010}, + {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, + {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010}, + {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210}, + {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce}, + {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c}, + {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444}, + {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019}, + {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000}, + {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, + {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000}, + {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000}, }; static const u32 ar9280Common_9280_2[][2] = { @@ -425,476 +424,471 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = { {0x00009918, 0x0000000b, 0x00000016}, }; -static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290}, - {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300}, - {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304}, - {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308}, - {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c}, - {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000}, - {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004}, - {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008}, - {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c}, - {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080}, - {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084}, - {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088}, - {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c}, - {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100}, - {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104}, - {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108}, - {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c}, - {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110}, - {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114}, - {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180}, - {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184}, - {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188}, - {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c}, - {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190}, - {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194}, - {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0}, - {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c}, - {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8}, - {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284}, - {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288}, - {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224}, - {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290}, - {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300}, - {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304}, - {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308}, - {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c}, - {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380}, - {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384}, - {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700}, - {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704}, - {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708}, - {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c}, - {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780}, - {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784}, - {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00}, - {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04}, - {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08}, - {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c}, - {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10}, - {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80}, - {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84}, - {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88}, - {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c}, - {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90}, - {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94}, - {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98}, - {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4}, - {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8}, - {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac}, - {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0}, - {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4}, - {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1}, - {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5}, - {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9}, - {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad}, - {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1}, - {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5}, - {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2}, - {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6}, - {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa}, - {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae}, - {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2}, - {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6}, - {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3}, - {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7}, - {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab}, - {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf}, - {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3}, - {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7}, - {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3}, - {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7}, - {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb}, - {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf}, - {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3}, - {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7}, - {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb}, - {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb}, - {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb}, - {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb}, - {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb}, - {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb}, - {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb}, - {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb}, - {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb}, - {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb}, - {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb}, - {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb}, - {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb}, - {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb}, - {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb}, - {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb}, - {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb}, - {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb}, - {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055}, - {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055}, +static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { + {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290}, + {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300}, + {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304}, + {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308}, + {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c}, + {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004}, + {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008}, + {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c}, + {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080}, + {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084}, + {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088}, + {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c}, + {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100}, + {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104}, + {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108}, + {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c}, + {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110}, + {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114}, + {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180}, + {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184}, + {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188}, + {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c}, + {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190}, + {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194}, + {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0}, + {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c}, + {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8}, + {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284}, + {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288}, + {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224}, + {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290}, + {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300}, + {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304}, + {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308}, + {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c}, + {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380}, + {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384}, + {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700}, + {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704}, + {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708}, + {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c}, + {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780}, + {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784}, + {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00}, + {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04}, + {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08}, + {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c}, + {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10}, + {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80}, + {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84}, + {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88}, + {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c}, + {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90}, + {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94}, + {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98}, + {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4}, + {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8}, + {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac}, + {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0}, + {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4}, + {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1}, + {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5}, + {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9}, + {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad}, + {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1}, + {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5}, + {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2}, + {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6}, + {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa}, + {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae}, + {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2}, + {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6}, + {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3}, + {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7}, + {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab}, + {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf}, + {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3}, + {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7}, + {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3}, + {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7}, + {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb}, + {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf}, + {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3}, + {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7}, + {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb}, + {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055}, + {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055}, }; -static const u32 ar9280Modes_original_rxgain_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000}, - {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000}, - {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000}, - {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000}, - {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000}, - {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000}, - {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004}, - {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008}, - {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c}, - {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080}, - {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084}, - {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088}, - {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c}, - {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100}, - {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104}, - {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108}, - {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c}, - {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110}, - {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114}, - {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180}, - {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184}, - {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188}, - {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c}, - {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190}, - {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194}, - {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0}, - {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c}, - {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8}, - {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284}, - {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288}, - {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224}, - {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290}, - {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300}, - {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304}, - {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308}, - {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c}, - {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380}, - {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384}, - {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700}, - {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704}, - {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708}, - {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c}, - {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780}, - {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784}, - {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00}, - {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04}, - {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08}, - {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c}, - {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80}, - {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84}, - {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88}, - {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c}, - {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90}, - {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80}, - {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84}, - {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88}, - {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c}, - {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90}, - {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c}, - {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310}, - {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384}, - {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388}, - {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324}, - {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704}, - {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4}, - {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8}, - {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710}, - {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714}, - {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720}, - {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724}, - {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728}, - {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c}, - {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0}, - {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4}, - {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8}, - {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0}, - {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4}, - {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8}, - {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5}, - {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9}, - {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad}, - {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1}, - {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5}, - {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9}, - {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5}, - {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9}, - {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1}, - {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5}, - {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9}, - {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6}, - {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca}, - {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce}, - {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2}, - {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6}, - {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3}, - {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7}, - {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb}, - {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf}, - {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7}, - {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db}, - {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db}, - {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db}, - {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db}, - {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063}, - {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063}, +static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { + {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004}, + {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008}, + {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c}, + {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080}, + {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084}, + {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088}, + {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c}, + {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100}, + {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104}, + {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108}, + {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c}, + {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110}, + {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114}, + {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180}, + {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184}, + {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188}, + {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c}, + {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190}, + {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194}, + {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0}, + {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c}, + {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8}, + {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284}, + {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288}, + {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224}, + {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290}, + {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300}, + {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304}, + {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308}, + {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c}, + {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380}, + {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384}, + {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700}, + {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704}, + {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708}, + {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c}, + {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780}, + {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784}, + {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00}, + {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04}, + {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08}, + {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c}, + {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80}, + {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84}, + {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88}, + {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c}, + {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90}, + {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80}, + {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84}, + {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88}, + {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c}, + {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90}, + {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c}, + {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310}, + {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384}, + {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388}, + {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324}, + {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704}, + {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4}, + {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8}, + {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710}, + {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714}, + {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720}, + {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724}, + {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728}, + {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c}, + {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0}, + {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4}, + {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8}, + {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0}, + {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4}, + {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8}, + {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5}, + {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9}, + {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad}, + {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1}, + {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5}, + {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9}, + {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5}, + {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9}, + {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1}, + {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5}, + {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9}, + {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6}, + {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca}, + {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce}, + {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2}, + {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6}, + {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3}, + {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7}, + {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb}, + {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf}, + {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7}, + {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db}, + {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db}, + {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db}, + {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db}, + {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063}, + {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063}, }; -static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290}, - {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300}, - {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304}, - {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308}, - {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c}, - {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000}, - {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004}, - {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008}, - {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c}, - {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080}, - {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084}, - {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088}, - {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c}, - {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100}, - {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104}, - {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108}, - {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c}, - {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110}, - {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114}, - {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180}, - {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184}, - {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188}, - {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c}, - {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190}, - {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194}, - {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0}, - {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c}, - {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8}, - {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284}, - {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288}, - {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224}, - {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290}, - {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300}, - {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304}, - {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308}, - {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c}, - {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380}, - {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384}, - {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700}, - {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704}, - {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708}, - {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c}, - {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780}, - {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784}, - {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00}, - {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04}, - {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08}, - {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c}, - {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80}, - {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84}, - {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88}, - {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c}, - {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90}, - {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80}, - {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84}, - {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88}, - {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c}, - {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90}, - {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310}, - {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314}, - {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320}, - {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324}, - {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328}, - {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c}, - {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330}, - {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334}, - {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321}, - {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325}, - {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329}, - {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d}, - {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331}, - {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335}, - {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322}, - {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326}, - {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a}, - {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e}, - {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332}, - {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336}, - {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323}, - {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327}, - {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b}, - {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f}, - {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333}, - {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337}, - {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343}, - {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347}, - {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b}, - {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f}, - {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353}, - {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357}, - {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b}, - {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b}, - {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b}, - {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b}, - {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b}, - {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b}, - {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b}, - {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b}, - {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b}, - {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b}, - {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b}, - {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b}, - {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b}, - {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a}, - {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a}, +static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { + {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290}, + {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300}, + {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304}, + {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308}, + {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c}, + {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000}, + {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004}, + {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008}, + {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c}, + {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080}, + {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084}, + {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088}, + {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c}, + {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100}, + {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104}, + {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108}, + {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c}, + {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110}, + {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114}, + {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180}, + {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184}, + {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188}, + {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c}, + {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190}, + {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194}, + {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0}, + {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c}, + {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8}, + {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284}, + {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288}, + {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224}, + {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290}, + {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300}, + {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304}, + {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308}, + {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c}, + {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380}, + {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384}, + {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700}, + {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704}, + {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708}, + {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c}, + {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780}, + {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784}, + {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00}, + {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04}, + {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08}, + {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c}, + {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80}, + {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84}, + {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88}, + {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c}, + {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90}, + {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80}, + {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84}, + {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88}, + {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c}, + {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90}, + {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310}, + {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314}, + {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320}, + {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324}, + {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328}, + {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c}, + {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330}, + {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334}, + {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321}, + {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325}, + {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329}, + {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d}, + {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331}, + {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335}, + {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322}, + {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326}, + {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a}, + {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e}, + {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332}, + {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336}, + {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323}, + {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327}, + {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b}, + {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f}, + {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333}, + {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337}, + {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343}, + {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347}, + {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b}, + {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f}, + {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353}, + {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357}, + {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b}, + {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a}, + {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a}, }; -static const u32 ar9280Modes_high_power_tx_gain_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652}, - {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce}, - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002}, - {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008}, - {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010}, - {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012}, - {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014}, - {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a}, - {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211}, - {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213}, - {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411}, - {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413}, - {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811}, - {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813}, - {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14}, - {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50}, - {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c}, - {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a}, - {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92}, - {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2}, - {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5}, - {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54}, - {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5}, - {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081}, - {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff}, - {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff}, - {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000}, - {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000}, - {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480}, - {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480}, +static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { + {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652}, + {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce}, + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002}, + {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008}, + {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010}, + {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012}, + {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014}, + {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a}, + {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211}, + {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213}, + {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411}, + {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413}, + {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811}, + {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813}, + {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14}, + {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50}, + {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c}, + {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a}, + {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92}, + {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2}, + {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5}, + {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54}, + {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5}, + {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081}, + {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff}, + {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff}, + {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000}, + {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000}, + {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480}, + {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480}, }; -static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652}, - {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce}, - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002}, - {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009}, - {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b}, - {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012}, - {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048}, - {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a}, - {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211}, - {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213}, - {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b}, - {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412}, - {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414}, - {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a}, - {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649}, - {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b}, - {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49}, - {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48}, - {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a}, - {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88}, - {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a}, - {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9}, - {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42}, - {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081}, - {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff}, - {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff}, - {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000}, - {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000}, - {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, - {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, +static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { + {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652}, + {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce}, + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002}, + {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009}, + {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b}, + {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012}, + {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048}, + {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a}, + {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211}, + {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213}, + {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b}, + {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412}, + {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414}, + {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a}, + {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649}, + {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b}, + {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49}, + {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48}, + {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a}, + {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88}, + {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a}, + {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9}, + {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42}, + {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081}, + {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff}, + {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff}, + {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000}, + {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000}, + {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, + {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, }; static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { @@ -953,310 +947,309 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9285Modes_9285_1_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620}, - {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053}, - {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053}, - {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, - {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e}, - {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20}, - {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d}, - {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020}, - {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c}, - {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084}, - {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088}, - {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c}, - {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100}, - {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104}, - {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108}, - {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c}, - {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110}, - {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114}, - {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180}, - {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184}, - {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188}, - {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c}, - {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190}, - {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194}, - {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0}, - {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c}, - {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8}, - {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284}, - {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288}, - {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224}, - {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290}, - {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300}, - {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304}, - {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308}, - {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c}, - {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380}, - {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384}, - {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700}, - {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704}, - {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708}, - {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c}, - {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780}, - {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784}, - {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00}, - {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04}, - {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08}, - {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c}, - {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80}, - {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84}, - {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88}, - {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c}, - {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90}, - {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80}, - {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84}, - {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88}, - {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c}, - {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90}, - {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c}, - {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310}, - {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384}, - {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388}, - {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324}, - {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704}, - {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4}, - {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8}, - {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710}, - {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714}, - {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720}, - {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724}, - {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728}, - {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c}, - {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0}, - {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4}, - {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8}, - {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0}, - {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4}, - {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8}, - {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5}, - {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9}, - {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad}, - {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1}, - {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5}, - {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9}, - {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5}, - {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9}, - {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1}, - {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5}, - {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9}, - {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6}, - {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca}, - {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce}, - {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2}, - {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6}, - {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3}, - {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7}, - {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb}, - {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf}, - {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7}, - {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084}, - {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088}, - {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c}, - {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100}, - {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104}, - {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108}, - {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c}, - {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110}, - {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114}, - {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180}, - {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184}, - {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188}, - {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c}, - {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190}, - {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194}, - {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0}, - {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c}, - {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8}, - {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284}, - {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288}, - {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224}, - {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290}, - {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300}, - {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304}, - {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308}, - {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c}, - {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380}, - {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384}, - {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700}, - {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704}, - {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708}, - {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c}, - {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780}, - {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784}, - {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00}, - {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04}, - {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08}, - {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c}, - {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80}, - {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84}, - {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88}, - {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c}, - {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90}, - {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80}, - {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84}, - {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88}, - {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c}, - {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90}, - {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c}, - {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310}, - {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384}, - {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388}, - {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324}, - {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704}, - {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4}, - {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8}, - {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710}, - {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714}, - {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720}, - {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724}, - {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728}, - {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c}, - {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0}, - {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4}, - {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8}, - {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0}, - {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4}, - {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8}, - {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5}, - {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9}, - {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad}, - {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1}, - {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5}, - {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9}, - {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5}, - {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9}, - {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1}, - {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5}, - {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9}, - {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6}, - {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca}, - {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce}, - {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2}, - {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6}, - {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3}, - {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7}, - {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb}, - {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf}, - {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7}, - {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004}, - {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000}, - {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e}, +static const u32 ar9285Modes_9285_1_2[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0}, + {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059}, + {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059}, + {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, + {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e}, + {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18}, + {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d}, + {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010}, + {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c}, + {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, + {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f}, + {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, + {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, + {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000}, + {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000}, + {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000}, + {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000}, + {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000}, + {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000}, + {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000}, + {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000}, + {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000}, + {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000}, + {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000}, + {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000}, + {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000}, + {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000}, + {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000}, + {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000}, + {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000}, + {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000}, + {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000}, + {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000}, + {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000}, + {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000}, + {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000}, + {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000}, + {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000}, + {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000}, + {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000}, + {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000}, + {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000}, + {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000}, + {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000}, + {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000}, + {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000}, + {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000}, + {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000}, + {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000}, + {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000}, + {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000}, + {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000}, + {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000}, + {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000}, + {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000}, + {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000}, + {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000}, + {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000}, + {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000}, + {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000}, + {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000}, + {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000}, + {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000}, + {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000}, + {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000}, + {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000}, + {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000}, + {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000}, + {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000}, + {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000}, + {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000}, + {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000}, + {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000}, + {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000}, + {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000}, + {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000}, + {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000}, + {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000}, + {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000}, + {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000}, + {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000}, + {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000}, + {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000}, + {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000}, + {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000}, + {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000}, + {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000}, + {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000}, + {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000}, + {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000}, + {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000}, + {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000}, + {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000}, + {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000}, + {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000}, + {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000}, + {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000}, + {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000}, + {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000}, + {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000}, + {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000}, + {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000}, + {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000}, + {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000}, + {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000}, + {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000}, + {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000}, + {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000}, + {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000}, + {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000}, + {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000}, + {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000}, + {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000}, + {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000}, + {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000}, + {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000}, + {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000}, + {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000}, + {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000}, + {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000}, + {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000}, + {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000}, + {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000}, + {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000}, + {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000}, + {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000}, + {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000}, + {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000}, + {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000}, + {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000}, + {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000}, + {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000}, + {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000}, + {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000}, + {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000}, + {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000}, + {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000}, + {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000}, + {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000}, + {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000}, + {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000}, + {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000}, + {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000}, + {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000}, + {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000}, + {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000}, + {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000}, + {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000}, + {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000}, + {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000}, + {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000}, + {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000}, + {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000}, + {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000}, + {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000}, + {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000}, + {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000}, + {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000}, + {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000}, + {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000}, + {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000}, + {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000}, + {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000}, + {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000}, + {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000}, + {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000}, + {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000}, + {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000}, + {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000}, + {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000}, + {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000}, + {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000}, + {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000}, + {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000}, + {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000}, + {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000}, + {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000}, + {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000}, + {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000}, + {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000}, + {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000}, + {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000}, + {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000}, + {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000}, + {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000}, + {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000}, + {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000}, + {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000}, + {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000}, + {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000}, + {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000}, + {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004}, + {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000}, + {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, }; static const u32 ar9285Common_9285_1_2[][2] = { @@ -1579,168 +1572,164 @@ static const u32 ar9285Common_9285_1_2[][2] = { {0x00007870, 0x10142c00}, }; -static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240}, - {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241}, - {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600}, - {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800}, - {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802}, - {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805}, - {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80}, - {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40}, - {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80}, - {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8}, - {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b}, - {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e}, - {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803}, - {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe}, - {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20}, - {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe}, - {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652}, - {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7}, - {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, - {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, +static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8}, + {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b}, + {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e}, + {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803}, + {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe}, + {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20}, + {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe}, + {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652}, + {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7}, + {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, + {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, }; -static const u32 ar9285Modes_original_tx_gain_9285_1_2[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208}, - {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608}, - {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618}, - {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9}, - {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710}, - {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718}, - {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758}, - {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a}, - {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e}, - {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f}, - {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8}, - {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b}, - {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e}, - {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801}, - {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe}, - {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20}, - {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, - {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, - {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652}, - {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c}, - {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, - {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, +static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8}, + {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b}, + {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e}, + {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801}, + {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe}, + {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20}, + {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, + {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, + {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652}, + {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c}, + {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, + {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, }; -static const u32 ar9285Modes_XE2_0_normal_power[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208}, - {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608}, - {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618}, - {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9}, - {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710}, - {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718}, - {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758}, - {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a}, - {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e}, - {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f}, - {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8}, - {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b}, - {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e}, - {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441}, - {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe}, - {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c}, - {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, - {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, - {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652}, - {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c}, - {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, - {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, - {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, +static const u32 ar9285Modes_XE2_0_normal_power[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8}, + {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b}, + {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae}, + {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441}, + {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe}, + {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c}, + {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, + {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, + {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652}, + {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c}, + {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, + {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c}, + {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, }; -static const u32 ar9285Modes_XE2_0_high_power[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240}, - {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241}, - {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600}, - {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800}, - {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802}, - {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805}, - {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80}, - {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40}, - {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80}, - {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8}, - {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b}, - {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e}, - {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443}, - {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe}, - {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c}, - {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe}, - {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652}, - {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7}, - {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, - {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, +static const u32 ar9285Modes_XE2_0_high_power[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000}, + {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8}, + {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b}, + {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e}, + {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443}, + {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe}, + {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c}, + {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe}, + {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652}, + {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7}, + {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, + {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, }; static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { @@ -1771,51 +1760,50 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9287Modes_9287_1_1[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00}, - {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440}, - {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300}, - {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200}, - {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e}, - {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001}, - {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007}, - {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0}, - {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2}, - {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e}, - {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20}, - {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881}, - {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898}, - {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b}, - {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d}, - {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010}, - {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, - {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, - {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210}, - {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce}, - {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c}, - {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4}, - {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444}, - {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e}, - {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +static const u32 ar9287Modes_9287_1_1[][6] = { + {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001}, + {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0}, + {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2}, + {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e}, + {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18}, + {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881}, + {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d}, + {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010}, + {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010}, + {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210}, + {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce}, + {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c}, + {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444}, + {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, + {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; static const u32 ar9287Common_9287_1_1[][2] = { @@ -2201,315 +2189,313 @@ static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = { {0x0000a1fc, 0xca9228ee}, }; -static const u32 ar9287Modes_tx_gain_9287_1_1[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002}, - {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a}, - {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c}, - {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b}, - {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a}, - {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a}, - {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a}, - {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a}, - {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a}, - {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a}, - {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a}, - {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c}, - {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc}, - {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4}, - {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc}, - {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede}, - {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e}, - {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e}, - {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e}, - {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062}, - {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064}, - {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4}, - {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa}, - {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac}, - {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4}, - {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4}, - {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134}, - {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174}, - {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c}, - {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e}, - {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be}, - {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe}, - {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000}, +static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002}, + {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a}, + {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c}, + {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b}, + {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a}, + {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a}, + {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a}, + {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a}, + {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a}, + {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a}, + {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a}, + {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c}, + {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc}, + {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4}, + {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc}, + {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede}, + {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e}, + {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e}, + {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e}, + {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062}, + {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064}, + {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4}, + {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa}, + {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac}, + {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4}, + {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4}, + {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134}, + {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174}, + {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c}, + {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e}, + {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be}, + {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe}, + {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000}, }; -static const u32 ar9287Modes_rx_gain_9287_1_1[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120}, - {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124}, - {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128}, - {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c}, - {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130}, - {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194}, - {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198}, - {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c}, - {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210}, - {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284}, - {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288}, - {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c}, - {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290}, - {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294}, - {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0}, - {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4}, - {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8}, - {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac}, - {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0}, - {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4}, - {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8}, - {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4}, - {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708}, - {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c}, - {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710}, - {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04}, - {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08}, - {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c}, - {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10}, - {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14}, - {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18}, - {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c}, - {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90}, - {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94}, - {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98}, - {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4}, - {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8}, - {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04}, - {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08}, - {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c}, - {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10}, - {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14}, - {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18}, - {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c}, - {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90}, - {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18}, - {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24}, - {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28}, - {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314}, - {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318}, - {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c}, - {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390}, - {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394}, - {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398}, - {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4}, - {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8}, - {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac}, - {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0}, - {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380}, - {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384}, - {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388}, - {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710}, - {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714}, - {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718}, - {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10}, - {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14}, - {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18}, - {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c}, - {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90}, - {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94}, - {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c}, - {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90}, - {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94}, - {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0}, - {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4}, - {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8}, - {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac}, - {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0}, - {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4}, - {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1}, - {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5}, - {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9}, - {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad}, - {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1}, - {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5}, - {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9}, - {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5}, - {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9}, - {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd}, - {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1}, - {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5}, - {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2}, - {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6}, - {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca}, - {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce}, - {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2}, - {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6}, - {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda}, - {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7}, - {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb}, - {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf}, - {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3}, - {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7}, - {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120}, - {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124}, - {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128}, - {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c}, - {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130}, - {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194}, - {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198}, - {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c}, - {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210}, - {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284}, - {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288}, - {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c}, - {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290}, - {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294}, - {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0}, - {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4}, - {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8}, - {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac}, - {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0}, - {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4}, - {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8}, - {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4}, - {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708}, - {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c}, - {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710}, - {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04}, - {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08}, - {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c}, - {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10}, - {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14}, - {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18}, - {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c}, - {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90}, - {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94}, - {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98}, - {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4}, - {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8}, - {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04}, - {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08}, - {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c}, - {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10}, - {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14}, - {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18}, - {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c}, - {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90}, - {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18}, - {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24}, - {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28}, - {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314}, - {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318}, - {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c}, - {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390}, - {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394}, - {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398}, - {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4}, - {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8}, - {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac}, - {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0}, - {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380}, - {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384}, - {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388}, - {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710}, - {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714}, - {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718}, - {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10}, - {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14}, - {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18}, - {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c}, - {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90}, - {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94}, - {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c}, - {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90}, - {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94}, - {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0}, - {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4}, - {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8}, - {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac}, - {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0}, - {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4}, - {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1}, - {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5}, - {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9}, - {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad}, - {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1}, - {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5}, - {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9}, - {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5}, - {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9}, - {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd}, - {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1}, - {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5}, - {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2}, - {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6}, - {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca}, - {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce}, - {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2}, - {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6}, - {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda}, - {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7}, - {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb}, - {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf}, - {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3}, - {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7}, - {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb}, - {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067}, - {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067}, +static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = { + {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, + {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, + {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, + {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c}, + {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130}, + {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194}, + {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198}, + {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c}, + {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210}, + {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284}, + {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288}, + {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c}, + {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290}, + {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294}, + {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0}, + {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4}, + {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8}, + {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac}, + {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0}, + {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4}, + {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8}, + {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4}, + {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708}, + {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c}, + {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710}, + {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04}, + {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08}, + {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c}, + {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10}, + {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14}, + {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18}, + {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c}, + {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90}, + {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94}, + {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98}, + {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4}, + {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8}, + {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04}, + {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08}, + {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c}, + {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10}, + {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14}, + {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18}, + {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c}, + {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90}, + {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18}, + {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24}, + {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28}, + {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314}, + {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318}, + {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c}, + {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390}, + {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394}, + {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398}, + {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4}, + {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8}, + {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac}, + {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0}, + {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380}, + {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384}, + {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388}, + {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710}, + {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714}, + {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718}, + {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10}, + {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14}, + {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18}, + {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c}, + {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90}, + {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94}, + {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c}, + {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90}, + {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94}, + {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0}, + {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4}, + {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8}, + {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac}, + {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0}, + {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4}, + {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1}, + {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5}, + {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9}, + {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad}, + {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1}, + {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5}, + {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9}, + {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5}, + {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9}, + {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd}, + {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1}, + {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5}, + {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2}, + {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6}, + {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca}, + {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce}, + {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2}, + {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6}, + {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda}, + {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7}, + {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb}, + {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf}, + {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3}, + {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7}, + {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb}, + {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, + {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, }; static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { @@ -2540,311 +2526,310 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9271Modes_9271[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, - {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300}, - {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, - {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001}, - {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, - {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e}, - {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620}, - {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053}, - {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053}, - {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, - {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e}, - {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, - {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00}, - {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310}, - {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d}, - {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020}, - {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c}, - {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, - {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f}, - {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, - {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, - {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084}, - {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088}, - {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c}, - {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100}, - {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104}, - {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108}, - {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c}, - {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110}, - {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114}, - {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180}, - {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184}, - {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188}, - {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c}, - {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190}, - {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194}, - {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0}, - {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c}, - {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8}, - {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284}, - {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288}, - {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224}, - {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290}, - {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300}, - {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304}, - {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308}, - {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c}, - {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380}, - {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384}, - {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700}, - {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704}, - {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708}, - {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c}, - {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780}, - {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784}, - {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00}, - {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04}, - {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08}, - {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c}, - {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80}, - {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84}, - {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88}, - {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c}, - {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90}, - {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80}, - {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84}, - {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88}, - {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c}, - {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90}, - {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c}, - {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310}, - {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384}, - {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388}, - {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324}, - {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704}, - {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4}, - {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8}, - {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710}, - {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714}, - {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720}, - {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724}, - {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728}, - {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c}, - {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0}, - {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4}, - {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8}, - {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0}, - {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4}, - {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8}, - {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5}, - {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9}, - {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad}, - {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1}, - {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5}, - {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9}, - {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5}, - {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9}, - {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1}, - {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5}, - {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9}, - {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6}, - {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca}, - {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce}, - {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2}, - {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6}, - {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3}, - {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7}, - {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb}, - {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf}, - {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7}, - {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084}, - {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088}, - {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c}, - {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100}, - {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104}, - {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108}, - {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c}, - {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110}, - {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114}, - {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180}, - {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184}, - {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188}, - {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c}, - {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190}, - {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194}, - {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0}, - {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c}, - {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8}, - {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284}, - {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288}, - {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224}, - {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290}, - {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300}, - {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304}, - {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308}, - {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c}, - {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380}, - {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384}, - {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700}, - {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704}, - {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708}, - {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c}, - {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780}, - {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784}, - {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00}, - {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04}, - {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08}, - {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c}, - {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80}, - {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84}, - {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88}, - {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c}, - {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90}, - {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80}, - {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84}, - {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88}, - {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c}, - {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90}, - {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c}, - {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310}, - {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384}, - {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388}, - {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324}, - {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704}, - {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4}, - {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8}, - {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710}, - {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714}, - {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720}, - {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724}, - {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728}, - {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c}, - {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0}, - {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4}, - {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8}, - {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0}, - {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4}, - {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8}, - {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5}, - {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9}, - {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad}, - {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1}, - {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5}, - {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9}, - {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5}, - {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9}, - {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1}, - {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5}, - {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9}, - {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6}, - {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca}, - {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce}, - {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2}, - {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6}, - {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3}, - {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7}, - {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb}, - {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf}, - {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7}, - {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db}, - {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004}, - {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000}, - {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000}, - {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, - {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000}, - {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e}, +static const u32 ar9271Modes_9271[][6] = { + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, + {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880}, + {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303}, + {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200}, + {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001}, + {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e}, + {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0}, + {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059}, + {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059}, + {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, + {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e}, + {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, + {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00}, + {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881}, + {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310}, + {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0}, + {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016}, + {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d}, + {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010}, + {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c}, + {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77}, + {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f}, + {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8}, + {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384}, + {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000}, + {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000}, + {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000}, + {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000}, + {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000}, + {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000}, + {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000}, + {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000}, + {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000}, + {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000}, + {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000}, + {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000}, + {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000}, + {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000}, + {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000}, + {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000}, + {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000}, + {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000}, + {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000}, + {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000}, + {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000}, + {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000}, + {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000}, + {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000}, + {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000}, + {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000}, + {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000}, + {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000}, + {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000}, + {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000}, + {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000}, + {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000}, + {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000}, + {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000}, + {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000}, + {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000}, + {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000}, + {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000}, + {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000}, + {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000}, + {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000}, + {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000}, + {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000}, + {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000}, + {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000}, + {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000}, + {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000}, + {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000}, + {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000}, + {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000}, + {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000}, + {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000}, + {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000}, + {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000}, + {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000}, + {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000}, + {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000}, + {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000}, + {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000}, + {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000}, + {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000}, + {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000}, + {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000}, + {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000}, + {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000}, + {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000}, + {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000}, + {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000}, + {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000}, + {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000}, + {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000}, + {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000}, + {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000}, + {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000}, + {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000}, + {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000}, + {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000}, + {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000}, + {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000}, + {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000}, + {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000}, + {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000}, + {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000}, + {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000}, + {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000}, + {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000}, + {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000}, + {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000}, + {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000}, + {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000}, + {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000}, + {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000}, + {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000}, + {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000}, + {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000}, + {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000}, + {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000}, + {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000}, + {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000}, + {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000}, + {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000}, + {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000}, + {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000}, + {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000}, + {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000}, + {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000}, + {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000}, + {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000}, + {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000}, + {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000}, + {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000}, + {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000}, + {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000}, + {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000}, + {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000}, + {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000}, + {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000}, + {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000}, + {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000}, + {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000}, + {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000}, + {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000}, + {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000}, + {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000}, + {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000}, + {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000}, + {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000}, + {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000}, + {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000}, + {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000}, + {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000}, + {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000}, + {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000}, + {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000}, + {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000}, + {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000}, + {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000}, + {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000}, + {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000}, + {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000}, + {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000}, + {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000}, + {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000}, + {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000}, + {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000}, + {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000}, + {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000}, + {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000}, + {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000}, + {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000}, + {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000}, + {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000}, + {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000}, + {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000}, + {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000}, + {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000}, + {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000}, + {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000}, + {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000}, + {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000}, + {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000}, + {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000}, + {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000}, + {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000}, + {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000}, + {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000}, + {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000}, + {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000}, + {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000}, + {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000}, + {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000}, + {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000}, + {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000}, + {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000}, + {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000}, + {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000}, + {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000}, + {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000}, + {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000}, + {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004}, + {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000}, + {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000}, + {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a}, + {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000}, + {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000}, + {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, }; static const u32 ar9271Common_9271[][2] = { @@ -3190,95 +3175,91 @@ static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { {0x0000a1fc, 0xca9228ee}, }; -static const u32 ar9271Modes_9271_1_0_only[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311}, - {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, +static const u32 ar9271Modes_9271_1_0_only[][6] = { + {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311}, + {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, }; -static const u32 ar9271Modes_9271_ANI_reg[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, - {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e}, - {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881}, - {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8}, - {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d}, - {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, +static const u32 ar9271Modes_9271_ANI_reg[][6] = { + {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, + {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e}, + {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, + {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881}, + {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8}, + {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d}, + {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, }; -static const u32 ar9271Modes_normal_power_tx_gain_9271[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208}, - {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608}, - {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610}, - {0x0000a314, 0x00000000, 0x00000000, 0x00024650, 0x00024650}, - {0x0000a318, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0}, - {0x0000a31c, 0x00000000, 0x00000000, 0x000316d2, 0x000316d2}, - {0x0000a320, 0x00000000, 0x00000000, 0x00039758, 0x00039758}, - {0x0000a324, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759}, - {0x0000a328, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c}, - {0x0000a330, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e}, - {0x0000a334, 0x000368de, 0x000368de, 0x0004979f, 0x0004979f}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0004d7df, 0x0004d7df}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029}, - {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff}, - {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, - {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, - {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21c652, 0x0a21c652}, - {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, - {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd}, - {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, - {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd}, - {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, - {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd}, +static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000}, + {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029}, + {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff}, + {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4}, + {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04}, + {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652}, + {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, + {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd}, + {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, + {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd}, + {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd}, + {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd}, }; -static const u32 ar9271Modes_high_power_tx_gain_9271[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000}, - {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200}, - {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201}, - {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240}, - {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241}, - {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600}, - {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800}, - {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802}, - {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805}, - {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41}, - {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00}, - {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40}, - {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80}, - {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de}, - {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e}, - {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e}, - {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df}, - {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b}, - {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff}, - {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba}, - {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, - {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652}, - {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, - {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063}, - {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63}, - {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063}, - {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63}, - {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063}, +static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { + {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000}, + {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000}, + {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000}, + {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000}, + {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000}, + {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000}, + {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000}, + {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000}, + {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000}, + {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000}, + {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000}, + {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000}, + {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000}, + {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000}, + {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000}, + {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000}, + {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000}, + {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b}, + {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff}, + {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6}, + {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00}, + {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652}, + {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7}, + {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063}, + {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63}, + {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063}, + {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63}, + {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063}, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 33deb0d574b0..45b262fe2c25 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u8 keyIx, + u32 txPower, u32 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar5416_desc *ads = AR5416DESC(ds); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index f2c6f2316a3b..a0aadaddd071 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0}, + {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f}, {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 3319a676c0fb..f48051c50092 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -615,10 +615,11 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, { int mp_max = -64, max_idx = 0; int mp_min = 63, min_idx = 0; - int mp_avg = 0, i, outlier_idx = 0, mp_count = 0; + int mp_avg = 0, i, outlier_idx = 0; /* find min/max mismatch across all calibrated gains */ for (i = 0; i < nmeasurement; i++) { + mp_avg += mp_coeff[i]; if (mp_coeff[i] > mp_max) { mp_max = mp_coeff[i]; max_idx = i; @@ -631,20 +632,10 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, /* find average (exclude max abs value) */ for (i = 0; i < nmeasurement; i++) { if ((abs(mp_coeff[i]) < abs(mp_max)) || - (abs(mp_coeff[i]) < abs(mp_min))) { + (abs(mp_coeff[i]) < abs(mp_min))) mp_avg += mp_coeff[i]; - mp_count++; - } } - - /* - * finding mean magnitude/phase if possible, otherwise - * just use the last value as the mean - */ - if (mp_count) - mp_avg /= mp_count; - else - mp_avg = mp_coeff[nmeasurement - 1]; + mp_avg /= (nmeasurement - 1); /* detect outlier */ if (abs(mp_max - mp_min) > max_delta) { @@ -848,8 +839,20 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_capabilities *pCap = &ah->caps; + int val; bool txiqcal_done = false; + val = REG_READ(ah, AR_ENT_OTP); + ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); + + /* Configure rx/tx chains before running AGC/TxiQ cals */ + if (val & AR_ENT_OTP_CHAIN2_DISABLE) + ar9003_hw_set_chain_masks(ah, 0x3, 0x3); + else + ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, + pCap->tx_chainmask); + /* Do Tx IQ Calibration */ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, @@ -884,6 +887,9 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah); + /* Revert chainmasks to their original values before NF cal */ + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + ath9k_hw_start_nfcal(ah, true); /* Initialize list pointers */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index cb4c32eaef61..908463915b99 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3318,7 +3318,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, word = kzalloc(2048, GFP_KERNEL); if (!word) - return -ENOMEM; + return -1; memcpy(mptr, &ar9300_default, mdata_size); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c index b6839e695270..ad2bb2bf4e8a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -21,7 +21,6 @@ #include "ar9340_initvals.h" #include "ar9330_1p1_initvals.h" #include "ar9330_1p2_initvals.h" -#include "ar9580_1p0_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -254,56 +253,6 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9485_1_1_pcie_phy_clkreq_disable_L1, ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), 2); - } else if (AR_SREV_9580(ah)) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9580_1p0_mac_core, - ARRAY_SIZE(ar9580_1p0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9580_1p0_mac_postamble, - ARRAY_SIZE(ar9580_1p0_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9580_1p0_baseband_core, - ARRAY_SIZE(ar9580_1p0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9580_1p0_baseband_postamble, - ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9580_1p0_radio_core, - ARRAY_SIZE(ar9580_1p0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9580_1p0_radio_postamble, - ARRAY_SIZE(ar9580_1p0_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9580_1p0_soc_preamble, - ARRAY_SIZE(ar9580_1p0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar9580_1p0_soc_postamble, - ARRAY_SIZE(ar9580_1p0_soc_postamble), 5); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9580_1p0_rx_gain_table, - ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9580_1p0_low_ob_db_tx_gain_table, - ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), - 5); - - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9580_1p0_modes_fast_clock, - ARRAY_SIZE(ar9580_1p0_modes_fast_clock), - 3); } else { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -399,11 +348,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9580_1p0_lowest_ob_db_tx_gain_table, - ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_lowest_ob_db_tx_gain_table_2p2, @@ -431,11 +375,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9580_1p0_high_ob_db_tx_gain_table, - ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_ob_db_tx_gain_table_2p2, @@ -463,11 +402,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_low_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), 5); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9580_1p0_low_ob_db_tx_gain_table, - ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_low_ob_db_tx_gain_table_2p2, @@ -495,11 +429,6 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9485Modes_high_power_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), 5); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9580_1p0_high_power_tx_gain_table, - ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table), - 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_power_tx_gain_table_2p2, @@ -534,11 +463,6 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9580_1p0_rx_gain_table, - ARRAY_SIZE(ar9580_1p0_rx_gain_table), - 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p2, @@ -566,11 +490,6 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); - else if (AR_SREV_9580(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9580_1p0_wo_xlna_rx_gain_table, - ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table), - 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_wo_xlna_rx_gain_table_2p2, @@ -597,10 +516,14 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) * register as the other analog registers. Hence the 9 writes. */ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, - bool power_off) + int restore, + int power_off) { + if (ah->is_pciexpress != true || ah->aspm_enabled != true) + return; + /* Nothing to do on restore for 11N */ - if (!power_off /* !restore */) { + if (!restore) { /* set bit 19 to allow forcing of pcie core into L1 state */ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c index d08ab930e430..1aadc4757e67 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -253,6 +253,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, return -EIO; } + if (status & AR_TxOpExceeded) + ts->ts_status |= ATH9K_TXERR_XTXOP; ts->ts_rateindex = MS(status, AR_FinalTxIdx); ts->ts_seqnum = MS(status, AR_SeqNum); ts->tid = MS(status, AR_TxTid); @@ -262,8 +264,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_status = 0; ts->ts_flags = 0; - if (status & AR_TxOpExceeded) - ts->ts_status |= ATH9K_TXERR_XTXOP; status = ACCESS_ONCE(ads->status2); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); @@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktlen, enum ath9k_pkt_type type, u32 txpower, - u8 keyIx, enum ath9k_key_type keyType, u32 flags) + u32 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar9003_txc *ads = (struct ar9003_txc *) ds; @@ -415,12 +415,36 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, u32 aggrLen) { +#define FIRST_DESC_NDELIMS 60 struct ar9003_txc *ads = (struct ar9003_txc *) ds; ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); - ads->ctl17 &= ~AR_AggrLen; - ads->ctl17 |= SM(aggrLen, AR_AggrLen); + if (ah->ent_mode & AR_ENT_OTP_MPSD) { + u32 ctl17, ndelim; + /* + * Add delimiter when using RTS/CTS with aggregation + * and non enterprise AR9003 card + */ + ctl17 = ads->ctl17; + ndelim = MS(ctl17, AR_PadDelim); + + if (ndelim < FIRST_DESC_NDELIMS) { + aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; + ndelim = FIRST_DESC_NDELIMS; + } + + ctl17 &= ~AR_AggrLen; + ctl17 |= SM(aggrLen, AR_AggrLen); + + ctl17 &= ~AR_PadDelim; + ctl17 |= SM(ndelim, AR_PadDelim); + + ads->ctl17 = ctl17; + } else { + ads->ctl17 &= ~AR_AggrLen; + ads->ctl17 |= SM(aggrLen, AR_AggrLen); + } } static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index bb2214f425b2..f80d1d633980 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah) if (delta > scale) return -1; - switch (get_streams(ah->txchainmask)) { + switch (get_streams(common->tx_chainmask)) { case 1: delta = 6; break; @@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah) default: delta = 0; ath_dbg(common, ATH_DBG_CALIBRATE, - "Invalid tx-chainmask: %u\n", ah->txchainmask); + "Invalid tx-chainmask: %u\n", common->tx_chainmask); } power += delta; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 33edb5653ca6..a0aaa6855486 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -482,7 +482,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); /* Enable 11n HT, 20 MHz */ - phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | + phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH | AR_PHY_GC_SHORT_GI_40 | enableDacFifo; /* Configure baseband for dynamic 20/40 operation */ @@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, udelay(synthDelay + BASE_ACTIVATE_DELAY); } -static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { switch (rx) { case 0x5: diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 3aca9fa2d27b..6de3f0bc18e6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -1124,4 +1124,6 @@ #define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f #define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0 +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); + #endif /* AR9003_PHY_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h deleted file mode 100644 index 06b3f0df9fad..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ /dev/null @@ -1,1673 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or 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. - */ - -#ifndef INITVALS_9580_1P0_H -#define INITVALS_9580_1P0_H - -/* AR9580 1.0 */ - -static const u32 ar9580_1p0_modes_fast_clock[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00001030, 0x00000268, 0x000004d0}, - {0x00001070, 0x0000018c, 0x00000318}, - {0x000010b0, 0x00000fd0, 0x00001fa0}, - {0x00008014, 0x044c044c, 0x08980898}, - {0x0000801c, 0x148ec02b, 0x148ec057}, - {0x00008318, 0x000044c0, 0x00008980}, - {0x00009e00, 0x0372131c, 0x0372131c}, - {0x0000a230, 0x0000000b, 0x00000016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -static const u32 ar9580_1p0_radio_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, - {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, - {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, - {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, -}; - -static const u32 ar9580_1p0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a9f6b}, - {0x0000980c, 0x04900000}, - {0x00009814, 0x3280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x6400a290}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x0d000600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x32840bbe}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009c04, 0xff55ff55}, - {0x00009c08, 0x0320ff55}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c0040b}, - {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038230c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0c6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x0d261820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0x00000000}, - {0x00009fc0, 0x803e4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x01193b93}, - {0x0000a20c, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a2a0, 0x00000001}, - {0x0000a2c0, 0x00000001}, - {0x0000a2c8, 0x00000000}, - {0x0000a2cc, 0x18c43433}, - {0x0000a2d4, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000000}, - {0x0000a3f8, 0x0c9bd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d001dce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00100000}, - {0x0000a440, 0x00000000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x05000080}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a458, 0x00000000}, - {0x0000a640, 0x00000000}, - {0x0000a644, 0x3fad9d74}, - {0x0000a648, 0x0048060a}, - {0x0000a64c, 0x00003c37}, - {0x0000a670, 0x03020100}, - {0x0000a674, 0x09080504}, - {0x0000a678, 0x0d0c0b0a}, - {0x0000a67c, 0x13121110}, - {0x0000a680, 0x31301514}, - {0x0000a684, 0x35343332}, - {0x0000a688, 0x00000036}, - {0x0000a690, 0x00000838}, - {0x0000a7c0, 0x00000000}, - {0x0000a7c4, 0xfffffffc}, - {0x0000a7c8, 0x00000000}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000000}, - {0x0000a8d0, 0x004b6a8e}, - {0x0000a8d4, 0x00000820}, - {0x0000a8dc, 0x00000000}, - {0x0000a8f0, 0x00000000}, - {0x0000a8f4, 0x00000000}, - {0x0000b2d0, 0x00000080}, - {0x0000b2d4, 0x00000000}, - {0x0000b2ec, 0x00000000}, - {0x0000b2f0, 0x00000000}, - {0x0000b2f4, 0x00000000}, - {0x0000b2f8, 0x00000000}, - {0x0000b408, 0x0e79e5c0}, - {0x0000b40c, 0x00820820}, - {0x0000b420, 0x00000000}, - {0x0000b8d0, 0x004b6a8e}, - {0x0000b8d4, 0x00000820}, - {0x0000b8dc, 0x00000000}, - {0x0000b8f0, 0x00000000}, - {0x0000b8f4, 0x00000000}, - {0x0000c2d0, 0x00000080}, - {0x0000c2d4, 0x00000000}, - {0x0000c2ec, 0x00000000}, - {0x0000c2f0, 0x00000000}, - {0x0000c2f4, 0x00000000}, - {0x0000c2f8, 0x00000000}, - {0x0000c408, 0x0e79e5c0}, - {0x0000c40c, 0x00820820}, - {0x0000c420, 0x00000000}, -}; - -static const u32 ar9580_1p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - -static const u32 ar9580_1p0_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, - {0x00000030, 0x00020085}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000000}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x000010f0, 0x00000100}, - {0x00001270, 0x00000000}, - {0x000012b0, 0x00000000}, - {0x000012f0, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00008000, 0x00000000}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000000}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008040, 0x00000000}, - {0x00008044, 0x00000000}, - {0x00008048, 0x00000000}, - {0x0000804c, 0xffffffff}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000310}, - {0x00008074, 0x00000020}, - {0x00008078, 0x00000000}, - {0x0000809c, 0x0000000f}, - {0x000080a0, 0x00000000}, - {0x000080a4, 0x02ff0000}, - {0x000080a8, 0x0e070605}, - {0x000080ac, 0x0000000d}, - {0x000080b0, 0x00000000}, - {0x000080b4, 0x00000000}, - {0x000080b8, 0x00000000}, - {0x000080bc, 0x00000000}, - {0x000080c0, 0x2a800000}, - {0x000080c4, 0x06900168}, - {0x000080c8, 0x13881c22}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00252500}, - {0x000080d4, 0x00a00000}, - {0x000080d8, 0x00400000}, - {0x000080dc, 0x00000000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x3f3f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00000000}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000000}, - {0x00008114, 0x000007ff}, - {0x00008118, 0x000000aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x0000ffff}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x33332210}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, - {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e800}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x40000000}, - {0x00008260, 0x00080922}, - {0x00008264, 0x9bc00010}, - {0x00008268, 0xffffffff}, - {0x0000826c, 0x0000ffff}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000004}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000140}, - {0x00008314, 0x00000000}, - {0x0000831c, 0x0000010d}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000700}, - {0x00008338, 0x00ff0000}, - {0x0000833c, 0x02400000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0xaa48105b}, - {0x00008348, 0x008f0000}, - {0x0000835c, 0x00000000}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0xffffffff}, - {0x00008394, 0xffffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x000083a4, 0x0000fa14}, - {0x000083a8, 0x000f0c00}, - {0x000083ac, 0x33332210}, - {0x000083b0, 0x33332210}, - {0x000083b4, 0x33332210}, - {0x000083b8, 0x33332210}, - {0x000083bc, 0x00000000}, - {0x000083c0, 0x00000000}, - {0x000083c4, 0x00000000}, - {0x000083c8, 0x00000000}, - {0x000083cc, 0x00000200}, - {0x000083d0, 0x000301ff}, -}; - -static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x7082708c, 0x7082708c, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, - {0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, - {0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, - {0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9580_1p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -}; - -static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, - {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, - {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, - {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, - {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9580_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x000040a4, 0x00a0c1c9}, - {0x00007008, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00007048, 0x00000008}, -}; - -static const u32 ar9580_1p0_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9580_1p0_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x0001604c, 0x76d005b5}, - {0x00016050, 0x556cf031}, - {0x00016054, 0x13449440}, - {0x00016058, 0x0c51c92c}, - {0x0001605c, 0x3db7fffc}, - {0x00016060, 0xfffffffc}, - {0x00016064, 0x000f0278}, - {0x0001606c, 0x6db60000}, - {0x00016080, 0x00000000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x54214514}, - {0x0001608c, 0x119f481e}, - {0x00016090, 0x24926490}, - {0x00016098, 0xd2888888}, - {0x000160a0, 0x0a108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92480080}, - {0x000160c0, 0x00adb6d0}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x01e6c000}, - {0x00016100, 0x3fffbe01}, - {0x00016104, 0xfff80000}, - {0x00016108, 0x00080010}, - {0x00016144, 0x02084080}, - {0x00016148, 0x00000000}, - {0x00016280, 0x058a0001}, - {0x00016284, 0x3d840208}, - {0x00016288, 0x05a20408}, - {0x0001628c, 0x00038c07}, - {0x00016290, 0x00000004}, - {0x00016294, 0x458aa14f}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00800700}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016440, 0x7f80fff8}, - {0x0001644c, 0x76d005b5}, - {0x00016450, 0x556cf031}, - {0x00016454, 0x13449440}, - {0x00016458, 0x0c51c92c}, - {0x0001645c, 0x3db7fffc}, - {0x00016460, 0xfffffffc}, - {0x00016464, 0x000f0278}, - {0x0001646c, 0x6db60000}, - {0x00016500, 0x3fffbe01}, - {0x00016504, 0xfff80000}, - {0x00016508, 0x00080010}, - {0x00016544, 0x02084080}, - {0x00016548, 0x00000000}, - {0x00016780, 0x00000000}, - {0x00016784, 0x00000000}, - {0x00016788, 0x00800700}, - {0x0001678c, 0x00800700}, - {0x00016790, 0x00800700}, - {0x00016794, 0x00000000}, - {0x00016798, 0x00000000}, - {0x0001679c, 0x00000000}, - {0x000167a0, 0x00000001}, - {0x000167a4, 0x00000001}, - {0x000167a8, 0x00000000}, - {0x000167ac, 0x00000000}, - {0x000167b0, 0x00000000}, - {0x000167b4, 0x00000000}, - {0x000167b8, 0x00000000}, - {0x000167bc, 0x00000000}, - {0x000167c0, 0x000000a0}, - {0x000167c4, 0x000c0000}, - {0x000167c8, 0x14021402}, - {0x000167cc, 0x00001402}, - {0x000167d0, 0x00000000}, - {0x000167d4, 0x00000000}, - {0x00016800, 0x36db6db6}, - {0x00016804, 0x6db6db40}, - {0x00016808, 0x73f00000}, - {0x0001680c, 0x00000000}, - {0x00016840, 0x7f80fff8}, - {0x0001684c, 0x76d005b5}, - {0x00016850, 0x556cf031}, - {0x00016854, 0x13449440}, - {0x00016858, 0x0c51c92c}, - {0x0001685c, 0x3db7fffc}, - {0x00016860, 0xfffffffc}, - {0x00016864, 0x000f0278}, - {0x0001686c, 0x6db60000}, - {0x00016900, 0x3fffbe01}, - {0x00016904, 0xfff80000}, - {0x00016908, 0x00080010}, - {0x00016944, 0x02084080}, - {0x00016948, 0x00000000}, - {0x00016b80, 0x00000000}, - {0x00016b84, 0x00000000}, - {0x00016b88, 0x00800700}, - {0x00016b8c, 0x00800700}, - {0x00016b90, 0x00800700}, - {0x00016b94, 0x00000000}, - {0x00016b98, 0x00000000}, - {0x00016b9c, 0x00000000}, - {0x00016ba0, 0x00000001}, - {0x00016ba4, 0x00000001}, - {0x00016ba8, 0x00000000}, - {0x00016bac, 0x00000000}, - {0x00016bb0, 0x00000000}, - {0x00016bb4, 0x00000000}, - {0x00016bb8, 0x00000000}, - {0x00016bbc, 0x00000000}, - {0x00016bc0, 0x000000a0}, - {0x00016bc4, 0x000c0000}, - {0x00016bc8, 0x14021402}, - {0x00016bcc, 0x00001402}, - {0x00016bd0, 0x00000000}, - {0x00016bd4, 0x00000000}, -}; - -static const u32 ar9580_1p0_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, - {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, - {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, - {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, - {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, - {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, - {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, - {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, - {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, - {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, - {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, - {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, -}; - -static const u32 ar9580_1p0_pcie_phy_clkreq_enable_L1[][2] = { - /* Addr allmodes */ - {0x00004040, 0x0835365e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -static const u32 ar9580_1p0_pcie_phy_clkreq_disable_L1[][2] = { - /* Addr allmodes */ - {0x00004040, 0x0831365e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = { - /* Addr allmodes */ - {0x00004040, 0x0831265e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -#endif /* INITVALS_9580_1P0_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 0fb4a26f8979..c03949eb37c8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -206,17 +206,16 @@ struct ath_atx_ac { }; struct ath_frame_info { - struct ath_buf *bf; int framelen; + u32 keyix; enum ath9k_key_type keytype; - u8 keyix; u8 retries; + u16 seqno; }; struct ath_buf_state { u8 bf_type; u8 bfs_paprd; - u16 seqno; unsigned long bfs_paprd_timestamp; }; @@ -236,7 +235,7 @@ struct ath_buf { struct ath_atx_tid { struct list_head list; - struct sk_buff_head buf_q; + struct list_head buf_q; struct ath_node *an; struct ath_atx_ac *ac; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; @@ -425,7 +424,6 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); #define ATH_PAPRD_TIMEOUT 100 /* msecs */ -void ath_reset_work(struct work_struct *work); void ath_hw_check(struct work_struct *work); void ath_hw_pll_work(struct work_struct *work); void ath_paprd_calibrate(struct work_struct *work); @@ -560,7 +558,8 @@ struct ath_ant_comb { #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) -#define SC_OP_PRIM_STA_VIF BIT(15) +#define SC_OP_ENABLE_APM BIT(15) +#define SC_OP_PRIM_STA_VIF BIT(16) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -605,7 +604,6 @@ struct ath_softc { struct mutex mutex; struct work_struct paprd_work; struct work_struct hw_check_work; - struct work_struct hw_reset_work; struct completion paprd_complete; unsigned int hw_busy_count; @@ -649,10 +647,10 @@ struct ath_softc { struct ath_descdma txsdma; struct ath_ant_comb ant_comb; - u8 ant_tx, ant_rx; }; void ath9k_tasklet(unsigned long data); +int ath_reset(struct ath_softc *sc, bool retry_tx); int ath_cabq_update(struct ath_softc *); static inline void ath_read_cachesize(struct ath_common *common, int *csz) @@ -666,11 +664,11 @@ extern int led_blink; extern bool is_ath9k_unloaded; irqreturn_t ath_isr(int irq, void *dev); +void ath9k_init_crypto(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); -void ath9k_reload_chainmask_settings(struct ath_softc *sc); void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); bool ath9k_uses_beacons(int type); diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 22e8e2580116..086c9c816bf7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -107,7 +107,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, series[0].Tries = 1; series[0].Rate = rate; series[0].ChSel = ath_txchainmask_reduction(sc, - ah->txchainmask, series[0].Rate); + common->tx_chainmask, series[0].Rate); series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, series, 4, 0); @@ -386,7 +386,9 @@ void ath_beacon_tasklet(unsigned long data) ath_dbg(common, ATH_DBG_BSTUCK, "beacon is officially stuck\n"); sc->sc_flags |= SC_OP_TSF_RESET; - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + spin_lock(&sc->sc_pcu_lock); + ath_reset(sc, true); + spin_unlock(&sc->sc_pcu_lock); } return; diff --git a/trunk/drivers/net/wireless/ath/ath9k/calib.c b/trunk/drivers/net/wireless/ath/ath9k/calib.c index ebaf304f464b..ac2da3cce788 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/calib.c @@ -82,6 +82,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, int16_t *nfarray) { struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; struct ath_nf_limits *limit; struct ath9k_nfcal_hist *h; bool high_nf_mid = false; @@ -93,7 +94,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, for (i = 0; i < NUM_NF_READINGS; i++) { if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan))) + ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) continue; h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.c b/trunk/drivers/net/wireless/ath/ath9k/common.c index dc705a224952..fa6bd2d189e5 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.c +++ b/trunk/drivers/net/wireless/ath/ath9k/common.c @@ -169,32 +169,6 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, } EXPORT_SYMBOL(ath9k_cmn_update_txpow); -void ath9k_cmn_init_crypto(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - int i = 0; - - /* Get the hardware key cache size. */ - common->keymax = AR_KEYTABLE_SIZE; - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) - common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < common->keymax; i++) - ath_hw_keyreset(common, (u16) i); -} -EXPORT_SYMBOL(ath9k_cmn_init_crypto); - static int __init ath9k_cmn_init(void) { return 0; diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.h b/trunk/drivers/net/wireless/ath/ath9k/common.h index ad14fecc76c6..77ec288b5a70 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.h +++ b/trunk/drivers/net/wireless/ath/ath9k/common.h @@ -62,4 +62,3 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, enum ath_stomp_type stomp_type); void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, u16 new_txpow, u16 *txpower); -void ath9k_cmn_init_crypto(struct ath_hw *ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 7f143872dc83..9bec3b89fb68 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); char buf[32]; unsigned int len; - len = sprintf(buf, "0x%08x\n", ah->txchainmask); + len = sprintf(buf, "0x%08x\n", common->tx_chainmask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long mask; char buf[32]; ssize_t len; @@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use if (strict_strtoul(buf, 0, &mask)) return -EINVAL; - ah->txchainmask = mask; - ah->caps.tx_chainmask = mask; + common->tx_chainmask = mask; + sc->sc_ah->caps.tx_chainmask = mask; return count; } @@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); char buf[32]; unsigned int len; - len = sprintf(buf, "0x%08x\n", ah->rxchainmask); + len = sprintf(buf, "0x%08x\n", common->rx_chainmask); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long mask; char buf[32]; ssize_t len; @@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use if (strict_strtoul(buf, 0, &mask)) return -EINVAL; - ah->rxchainmask = mask; - ah->caps.rx_chainmask = mask; + common->rx_chainmask = mask; + sc->sc_ah->caps.rx_chainmask = mask; return count; } @@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf, " tid: %p %s %s %i %p %p\n", tid, tid->sched ? "sched" : "idle", tid->paused ? "paused" : "running", - skb_queue_empty(&tid->buf_q), + list_empty(&tid->buf_q), tid->an, tid->ac); if (len >= size) goto done; @@ -828,8 +828,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq) { -#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ - [sc->debug.tsidx].c) int qnum = txq->axq_qnum; TX_STAT_INC(qnum, tx_pkts_all); @@ -859,26 +857,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); - - spin_lock(&sc->debug.samp_lock); - TX_SAMP_DBG(jiffies) = jiffies; - TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; - TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1; - TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2; - TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0; - TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1; - TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2; - TX_SAMP_DBG(rateindex) = ts->ts_rateindex; - TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK); - TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry; - TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry; - TX_SAMP_DBG(rssi) = ts->ts_rssi; - TX_SAMP_DBG(tid) = ts->tid; - TX_SAMP_DBG(qid) = ts->qid; - sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); - -#undef TX_SAMP_DBG } static const struct file_operations fops_xmit = { @@ -1017,8 +995,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ -#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ - [sc->debug.rsidx].c) u32 phyerr; @@ -1054,25 +1030,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; - spin_lock(&sc->debug.samp_lock); - RX_SAMP_DBG(jiffies) = jiffies; - RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; - RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1; - RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2; - RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0; - RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1; - RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2; - RX_SAMP_DBG(antenna) = rs->rs_antenna; - RX_SAMP_DBG(rssi) = rs->rs_rssi; - RX_SAMP_DBG(rate) = rs->rs_rate; - RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon; - - sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); - #undef RX_STAT_INC #undef RX_PHY_ERR_INC -#undef RX_SAMP_DBG } static const struct file_operations fops_recv = { @@ -1204,59 +1163,6 @@ static const struct file_operations fops_regdump = { .llseek = default_llseek,/* read accesses f_pos */ }; -static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; - struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; - u32 len = 0, size = 1500; - u32 i, j; - ssize_t retval = 0; - char *buf; - u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; - u8 nread; - - buf = kzalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += snprintf(buf + len, size - len, - "Channel Noise Floor : %d\n", ah->noise); - len += snprintf(buf + len, size - len, - "Chain | privNF | # Readings | NF Readings\n"); - for (i = 0; i < NUM_NF_READINGS; i++) { - if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) - continue; - - nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; - len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t", - i, h[i].privNF, nread); - for (j = 0; j < nread; j++) - len += snprintf(buf + len, size - len, - " %d", h[i].nfCalBuffer[j]); - len += snprintf(buf + len, size - len, "\n"); - } - - if (len > size) - len = size; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; -} - -static const struct file_operations fops_dump_nfcal = { - .read = read_file_dump_nfcal, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1313,277 +1219,6 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; -void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - unsigned long flags; - int i; - - ath9k_ps_wakeup(sc); - - spin_lock_bh(&sc->debug.samp_lock); - - spin_lock_irqsave(&common->cc_lock, flags); - ath_hw_cycle_counters_update(common); - - ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles; - ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy; - ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame; - ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame; - spin_unlock_irqrestore(&common->cc_lock, flags); - - ATH_SAMP_DBG(noise) = ah->noise; - - REG_WRITE_D(ah, AR_MACMISC, - ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | - (AR_MACMISC_MISC_OBS_BUS_1 << - AR_MACMISC_MISC_OBS_BUS_MSB_S))); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah, - AR_DMADBG_0 + (i * sizeof(u32))); - - ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1); - ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR); - - memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist, - sizeof(ATH_SAMP_DBG(nfCalHist))); - - sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock_bh(&sc->debug.samp_lock); - ath9k_ps_restore(sc); - -#undef ATH_SAMP_DBG -} - -static int open_file_bb_mac_samps(struct inode *inode, struct file *file) -{ -#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c - struct ath_softc *sc = inode->i_private; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; - struct ath_dbg_bb_mac_samp *bb_mac_samp; - struct ath9k_nfcal_hist *h; - int i, j, qcuOffset = 0, dcuOffset = 0; - u32 *qcuBase, *dcuBase, size = 30000, len = 0; - u32 sampidx = 0; - u8 *buf; - u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; - u8 nread; - - if (sc->sc_flags & SC_OP_INVALID) - return -EAGAIN; - - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - if (!bb_mac_samp) { - vfree(buf); - return -ENOMEM; - } - /* Account the current state too */ - ath9k_debug_samp_bb_mac(sc); - - spin_lock_bh(&sc->debug.samp_lock); - memcpy(bb_mac_samp, sc->debug.bb_mac_samp, - sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - len += snprintf(buf + len, size - len, - "Current Sample Index: %d\n", sc->debug.sampidx); - spin_unlock_bh(&sc->debug.samp_lock); - - len += snprintf(buf + len, size - len, - "Raw DMA Debug Dump:\n"); - len += snprintf(buf + len, size - len, "Sample |\t"); - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i); - len += snprintf(buf + len, size - len, "\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - len += snprintf(buf + len, size - len, "%d\t", sampidx); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " %08x\t", - ATH_SAMP_DBG(dma_dbg_reg_vals[i])); - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, "\n"); - - len += snprintf(buf + len, size - len, - "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - for (i = 0; i < ATH9K_NUM_QUEUES; i++, - qcuOffset += 4, dcuOffset += 5) { - if (i == 8) { - qcuOffset = 0; - qcuBase++; - } - - if (i == 6) { - dcuOffset = 0; - dcuBase++; - } - if (!sc->debug.stats.txstats[i].queued) - continue; - - len += snprintf(buf + len, size - len, - "%4d %7d %2x %1x %2x %2x\n", - sampidx, i, - (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, - (*qcuBase & (0x8 << qcuOffset)) >> - (qcuOffset + 3), - ATH_SAMP_DBG(dma_dbg_reg_vals[2]) & - (0x7 << (i * 3)) >> (i * 3), - (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); - } - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, - "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp " - "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 " - "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22); - len += snprintf(buf + len, size - len, "%7x %8x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3)); - len += snprintf(buf + len, size - len, "%7x %7x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25, - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27); - len += snprintf(buf + len, size - len, "%7d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17); - len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n", - ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr)); - } - - len += snprintf(buf + len, size - len, - "Sample ChNoise Chain privNF #Reading Readings\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - h = ATH_SAMP_DBG(nfCalHist); - if (!ATH_SAMP_DBG(noise)) - continue; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) - continue; - - nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - - h[i].invalidNFcount; - len += snprintf(buf + len, size - len, - "%4d %5d %4d\t %d\t %d\t", - sampidx, ATH_SAMP_DBG(noise), - i, h[i].privNF, nread); - for (j = 0; j < nread; j++) - len += snprintf(buf + len, size - len, - " %d", h[i].nfCalBuffer[j]); - len += snprintf(buf + len, size - len, "\n"); - } - } - len += snprintf(buf + len, size - len, "\nCycle counters:\n" - "Sample Total Rxbusy Rxframes Txframes\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - if (!ATH_SAMP_DBG(cc.cycles)) - continue; - len += snprintf(buf + len, size - len, - "%4d %08x %08x %08x %08x\n", - sampidx, ATH_SAMP_DBG(cc.cycles), - ATH_SAMP_DBG(cc.rx_busy), - ATH_SAMP_DBG(cc.rx_frame), - ATH_SAMP_DBG(cc.tx_frame)); - } - - len += snprintf(buf + len, size - len, "Tx status Dump :\n"); - len += snprintf(buf + len, size - len, - "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " - "isok rts_fail data_fail rate tid qid tx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(ts[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%4d \t" - "%8d %4d %4d %4d %4d %4d %4d %4d %4d " - "%4d %4d %2d %2d %d\n", - sampidx, - ATH_SAMP_DBG(ts[i].rssi_ctl0), - ATH_SAMP_DBG(ts[i].rssi_ctl1), - ATH_SAMP_DBG(ts[i].rssi_ctl2), - ATH_SAMP_DBG(ts[i].rssi_ext0), - ATH_SAMP_DBG(ts[i].rssi_ext1), - ATH_SAMP_DBG(ts[i].rssi_ext2), - ATH_SAMP_DBG(ts[i].rssi), - ATH_SAMP_DBG(ts[i].isok), - ATH_SAMP_DBG(ts[i].rts_fail_cnt), - ATH_SAMP_DBG(ts[i].data_fail_cnt), - ATH_SAMP_DBG(ts[i].rateindex), - ATH_SAMP_DBG(ts[i].tid), - ATH_SAMP_DBG(ts[i].qid), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(ts[i].jiffies))); - } - } - - len += snprintf(buf + len, size - len, "Rx status Dump :\n"); - len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 " - "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(rs[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%4d \t" - "%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n", - sampidx, - ATH_SAMP_DBG(rs[i].rssi_ctl0), - ATH_SAMP_DBG(rs[i].rssi_ctl1), - ATH_SAMP_DBG(rs[i].rssi_ctl2), - ATH_SAMP_DBG(rs[i].rssi_ext0), - ATH_SAMP_DBG(rs[i].rssi_ext1), - ATH_SAMP_DBG(rs[i].rssi_ext2), - ATH_SAMP_DBG(rs[i].rssi), - ATH_SAMP_DBG(rs[i].is_mybeacon) ? - "True" : "False", - ATH_SAMP_DBG(rs[i].antenna), - ATH_SAMP_DBG(rs[i].rate), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(rs[i].jiffies))); - } - } - - vfree(bb_mac_samp); - file->private_data = buf; - - return 0; -#undef ATH_SAMP_DBG -} - -static const struct file_operations fops_samps = { - .open = open_file_bb_mac_samps, - .read = ath9k_debugfs_read_buf, - .release = ath9k_debugfs_release_buf, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - - int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1627,14 +1262,10 @@ int ath9k_init_debug(struct ath_hw *ah) &ah->config.cwm_ignore_extcca); debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_regdump); - debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_dump_nfcal); debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_base_eeprom); debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_modal_eeprom); - debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_samps); debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); @@ -1643,9 +1274,5 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); sc->debug.regidx = 0; - memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp)); - sc->debug.sampidx = 0; - sc->debug.tsidx = 0; - sc->debug.rsidx = 0; return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 95f85bdc8db7..4a04510e1111 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -177,57 +177,14 @@ struct ath_stats { struct ath_rx_stats rxstats; }; -#define ATH_DBG_MAX_SAMPLES 10 -struct ath_dbg_bb_mac_samp { - u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS]; - u32 pcu_obs, pcu_cr, noise; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool isok; - u8 rts_fail_cnt; - u8 data_fail_cnt; - u8 rateindex; - u8 qid; - u8 tid; - } ts[ATH_DBG_MAX_SAMPLES]; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool is_mybeacon; - u8 antenna; - u8 rate; - } rs[ATH_DBG_MAX_SAMPLES]; - struct ath_cycle_counters cc; - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -}; - struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; struct ath_stats stats; - spinlock_t samp_lock; - struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; - u8 sampidx; - u8 tsidx; - u8 rsidx; }; int ath9k_init_debug(struct ath_hw *ah); -void ath9k_debug_samp_bb_mac(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq); @@ -240,10 +197,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } -static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -} - static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c index ea658e794cbd..1c6ce0442e2f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -349,7 +349,10 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, case EEP_ANT_DIV_CTL1: return pModal->antdiv_ctl1; case EEP_TXGAIN_TYPE: - return pBase->txGainType; + if (ver_minor >= AR5416_EEP_MINOR_VER_19) + return pBase->txGainType; + else + return AR5416_EEP_TXGAIN_ORIGINAL; default: return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 966661c9e586..19aa5b724887 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv, memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); /* ath9k_htc supports only 1 or 2 stream devices */ - tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2); - rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2); + tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); + rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); ath_dbg(common, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", @@ -572,6 +572,25 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) return -EINVAL; } +static void ath9k_init_crypto(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + int i = 0; + + /* Get the hardware key cache size. */ + common->keymax = AR_KEYTABLE_SIZE; + + if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) + common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < common->keymax; i++) + ath_hw_keyreset(common, (u16) i); +} + static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) { if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { @@ -601,6 +620,9 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) { struct ath_common *common = ath9k_hw_common(priv->ah); + common->tx_chainmask = priv->ah->caps.tx_chainmask; + common->rx_chainmask = priv->ah->caps.rx_chainmask; + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); priv->ah->opmode = NL80211_IFTYPE_STATION; @@ -698,7 +720,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) priv->cur_beacon_conf.bslot[i] = NULL; - ath9k_cmn_init_crypto(ah); + ath9k_init_crypto(priv); ath9k_init_channels_rates(priv); ath9k_init_misc(priv); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 495fdf680a6c..7212acb2bd6c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -826,7 +826,8 @@ void ath9k_htc_ani_work(struct work_struct *work) if (longcal || shortcal) common->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, - ah->rxchainmask, longcal); + common->rx_chainmask, + longcal); ath9k_htc_ps_restore(priv); } @@ -1299,7 +1300,6 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, if (priv->op_flags & OP_INVALID) { ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, "Unable to configure filter on invalid state\n"); - mutex_unlock(&priv->mutex); return; } ath9k_htc_ps_wakeup(priv); @@ -1736,22 +1736,6 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, return ret; } - -static int ath9k_htc_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; - - stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; - stats->dot11RTSFailureCount = mib_stats->rts_bad; - stats->dot11FCSErrorCount = mib_stats->fcs_bad; - stats->dot11RTSSuccessCount = mib_stats->rts_good; - - return 0; -} - struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1775,5 +1759,4 @@ struct ieee80211_ops ath9k_htc_ops = { .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, .set_bitrate_mask = ath9k_htc_set_bitrate_mask, - .get_stats = ath9k_htc_get_stats, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h index dd9003ee123b..cb29e8875386 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -22,12 +22,10 @@ /* Hardware core and driver accessible callbacks */ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, - bool power_off) + int restore, + int power_off) { - if (ah->aspm_enabled != true) - return; - - ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off); + ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); } static inline void ath9k_hw_rxena(struct ath_hw *ah) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index f2065fce4ec9..db44e5b0c98b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -440,7 +440,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) if (AR_SREV_9100(ah)) ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = ATH9K_SLOT_TIME_9; + ah->slottime = 20; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; } @@ -603,7 +603,10 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_regs(ah); - if (!ah->is_pciexpress) + + if (ah->is_pciexpress) + ath9k_hw_aspm_init(ah); + else ath9k_hw_disablepcie(ah); if (!AR_SREV_9300_20_OR_LATER(ah)) @@ -618,9 +621,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (r) return r; - if (ah->is_pciexpress) - ath9k_hw_aspm_init(ah); - r = ath9k_hw_init_macaddr(ah); if (r) { ath_err(common, "Failed to initialize MAC address\n"); @@ -663,7 +663,6 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_AR9485_PCIE: case AR9300_DEVID_AR9330: case AR9300_DEVID_AR9340: - case AR9300_DEVID_AR9580: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) @@ -960,7 +959,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &common->hw->conf; const struct ath9k_channel *chan = ah->curchan; - int acktimeout, ctstimeout; + int acktimeout; int slottime; int sifstime; int rx_lat = 0, tx_lat = 0, eifs = 0; @@ -975,10 +974,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) if (ah->misc_mode != 0) REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); - if (IS_CHAN_A_FAST_CLOCK(ah, chan)) - rx_lat = 41; - else - rx_lat = 37; + rx_lat = 37; tx_lat = 54; if (IS_CHAN_HALF_RATE(chan)) { @@ -992,7 +988,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) sifstime = 32; } else if (IS_CHAN_QUARTER_RATE(chan)) { eifs = 340; - rx_lat = (rx_lat * 4) - 1; + rx_lat *= 4; tx_lat *= 4; if (IS_CHAN_A_FAST_CLOCK(ah, chan)) tx_lat += 22; @@ -1000,14 +996,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) slottime = 21; sifstime = 64; } else { - if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { - eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO; - reg = AR_USEC_ASYNC_FIFO; - } else { - eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/ - common->clockrate; - reg = REG_READ(ah, AR_USEC); - } + eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS); + reg = REG_READ(ah, AR_USEC); rx_lat = MS(reg, AR_USEC_RX_LAT); tx_lat = MS(reg, AR_USEC_TX_LAT); @@ -1020,7 +1010,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) /* As defined by IEEE 802.11-2007 17.3.8.6 */ acktimeout = slottime + sifstime + 3 * ah->coverage_class; - ctstimeout = acktimeout; /* * Workaround for early ACK timeouts, add an offset to match the @@ -1035,7 +1024,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) ath9k_hw_set_sifs_time(ah, sifstime); ath9k_hw_setslottime(ah, slottime); ath9k_hw_set_ack_timeout(ah, acktimeout); - ath9k_hw_set_cts_timeout(ah, ctstimeout); + ath9k_hw_set_cts_timeout(ah, acktimeout); if (ah->globaltxtimeout != (u32) -1) ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); @@ -1479,6 +1468,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u64 tsf = 0; int i, r; + ah->txchainmask = common->tx_chainmask; + ah->rxchainmask = common->rx_chainmask; + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; @@ -2092,8 +2084,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); - ah->txchainmask = pCap->tx_chainmask; - ah->rxchainmask = pCap->rx_chainmask; ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; @@ -2450,13 +2440,13 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath9k_channel *chan = ah->curchan; struct ieee80211_channel *channel = chan->chan; - int reg_pwr = min_t(int, MAX_RATE_POWER, limit); + int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit); int chan_pwr = channel->max_power * 2; if (test) reg_pwr = chan_pwr = MAX_RATE_POWER; - regulatory->power_limit = reg_pwr; + regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); ah->eep_ops->set_txpower(ah, chan, ath9k_regd_get_ctl(regulatory, chan), @@ -2763,7 +2753,6 @@ static struct { { AR_SREV_VERSION_9271, "9271" }, { AR_SREV_VERSION_9300, "9300" }, { AR_SREV_VERSION_9330, "9330" }, - { AR_SREV_VERSION_9340, "9340" }, { AR_SREV_VERSION_9485, "9485" }, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index c8af86c795e5..4fbcced2828c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -45,7 +45,6 @@ #define AR9300_DEVID_PCIE 0x0030 #define AR9300_DEVID_AR9340 0x0031 #define AR9300_DEVID_AR9485_PCIE 0x0032 -#define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9330 0x0035 #define AR5416_AR9100_DEVID 0x000b @@ -607,7 +606,8 @@ struct ath_hw_private_ops { */ struct ath_hw_ops { void (*config_pci_powersave)(struct ath_hw *ah, - bool power_off); + int restore, + int power_off); void (*rx_enable)(struct ath_hw *ah); void (*set_desc_link)(void *ds, u32 link); bool (*calibrate)(struct ath_hw *ah, @@ -623,7 +623,7 @@ struct ath_hw_ops { struct ath_tx_status *ts); void (*set11n_txdesc)(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u8 keyIx, + u32 txPower, u32 keyIx, enum ath9k_key_type keyType, u32 flags); void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, @@ -1037,6 +1037,10 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); void ath9k_hw_proc_mib_event(struct ath_hw *ah); void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); +#define ATH_PCIE_CAP_LINK_CTRL 0x70 +#define ATH_PCIE_CAP_LINK_L0S 1 +#define ATH_PCIE_CAP_LINK_L1 2 + #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index 9b34c4bab937..db38a58e752d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_softc *sc, /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams); - rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams); + tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); + rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); ath_dbg(common, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", @@ -404,6 +404,31 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, return error; } +void ath9k_init_crypto(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int i = 0; + + /* Get the hardware key cache size. */ + common->keymax = AR_KEYTABLE_SIZE; + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < common->keymax; i++) + ath_hw_keyreset(common, (u16) i); + + /* + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. + */ + if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) + common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; +} + static int ath9k_init_btcoex(struct ath_softc *sc) { struct ath_txq *txq; @@ -506,6 +531,9 @@ static void ath9k_init_misc(struct ath_softc *sc) sc->sc_flags |= SC_OP_RXAGGR; } + common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; + common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; + ath9k_hw_set_diversity(sc->sc_ah, true); sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); @@ -569,7 +597,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); - spin_lock_init(&sc->debug.samp_lock); INIT_LIST_HEAD(&sc->nodes); #endif tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); @@ -603,7 +630,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, if (ret) goto err_btcoex; - ath9k_cmn_init_crypto(sc->sc_ah); + ath9k_init_crypto(sc); ath9k_init_misc(sc); return 0; @@ -643,8 +670,10 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) static void ath9k_init_txpower_limits(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_channel *curchan = ah->curchan; + ah->txchainmask = common->tx_chainmask; if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) @@ -653,22 +682,9 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc) ah->curchan = curchan; } -void ath9k_reload_chainmask_settings(struct ath_softc *sc) -{ - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)) - return; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); -} - - void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); + struct ath_common *common = ath9k_hw_common(sc->sc_ah); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | @@ -706,16 +722,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); - hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; - hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; - - /* single chain devices with rx diversity */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) - hw->wiphy->available_antennas_rx = BIT(0) | BIT(1); - - sc->ant_rx = hw->wiphy->available_antennas_rx; - sc->ant_tx = hw->wiphy->available_antennas_tx; - #ifdef CONFIG_ATH9K_RATE_CONTROL hw->rate_control_algorithm = "ath9k_rate_control"; #endif @@ -727,7 +733,12 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; - ath9k_reload_chainmask_settings(sc); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); + } SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } @@ -795,7 +806,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, goto error_world; } - INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.c b/trunk/drivers/net/wireless/ath/ath9k/mac.c index 7ce9b320f0d9..0f90e1521ffe 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.c @@ -345,8 +345,21 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); qi->tqi_type = type; - qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; - (void) ath9k_hw_set_txq_props(ah, q, qinfo); + if (qinfo == NULL) { + qi->tqi_qflags = + TXQ_FLAG_TXOKINT_ENABLE + | TXQ_FLAG_TXERRINT_ENABLE + | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; + (void) ath9k_hw_set_txq_props(ah, q, qinfo); + } return q; } @@ -551,7 +564,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) EXPORT_SYMBOL(ath9k_hw_resettxqueue); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_rx_status *rs) + struct ath_rx_status *rs, u64 tsf) { struct ar5416_desc ads; struct ar5416_desc *adsp = AR5416DESC(ds); diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h index acb83bfd05a0..8e848c4d16ba 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h @@ -146,7 +146,6 @@ struct ath_rx_status { u8 rs_moreaggr; u8 rs_num_delims; u8 rs_flags; - bool is_mybeacon; u32 evm0; u32 evm1; u32 evm2; @@ -195,7 +194,7 @@ struct ath_htc_rx_status { #define ATH9K_RX_DECRYPT_BUSY 0x40 #define ATH9K_RXKEYIX_INVALID ((u8)-1) -#define ATH9K_TXKEYIX_INVALID ((u8)-1) +#define ATH9K_TXKEYIX_INVALID ((u32)-1) enum ath9k_phyerr { ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ @@ -688,7 +687,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - struct ath_rx_status *rs); + struct ath_rx_status *rs, u64 tsf); void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags); bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index c8ac2ce61ffe..1e7fe8c0e119 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -212,58 +212,83 @@ static int ath_update_survey_stats(struct ath_softc *sc) return ret; } -static void __ath_cancel_work(struct ath_softc *sc) +/* + * Set/change channels. If the channel is really being changed, it's done + * by reseting the chip. To accomplish this we must first cleanup any pending + * DMA, then restart stuff. +*/ +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, + struct ath9k_channel *hchan) { + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; + bool fastcc = true, stopped; + struct ieee80211_channel *channel = hw->conf.channel; + struct ath9k_hw_cal_data *caldata = NULL; + int r; + + if (sc->sc_flags & SC_OP_INVALID) + return -EIO; + + sc->hw_busy_count = 0; + + del_timer_sync(&common->ani.timer); cancel_work_sync(&sc->paprd_work); cancel_work_sync(&sc->hw_check_work); cancel_delayed_work_sync(&sc->tx_complete_work); cancel_delayed_work_sync(&sc->hw_pll_work); -} -static void ath_cancel_work(struct ath_softc *sc) -{ - __ath_cancel_work(sc); - cancel_work_sync(&sc->hw_reset_work); -} + ath9k_ps_wakeup(sc); -static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - bool ret; + spin_lock_bh(&sc->sc_pcu_lock); - ieee80211_stop_queues(sc->hw); + /* + * This is only performed if the channel settings have + * actually changed. + * + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the + * hardware at the new frequency, and then re-enable + * the relevant bits of the h/w. + */ + ath9k_hw_disable_interrupts(ah); + stopped = ath_drain_all_txq(sc, false); - sc->hw_busy_count = 0; - del_timer_sync(&common->ani.timer); + if (!ath_stoprecv(sc)) + stopped = false; - ath9k_debug_samp_bb_mac(sc); - ath9k_hw_disable_interrupts(ah); + if (!ath9k_hw_check_alive(ah)) + stopped = false; - ret = ath_drain_all_txq(sc, retry_tx); + /* XXX: do not flush receive queue here. We don't want + * to flush data frames already in queue because of + * changing channel. */ - if (!ath_stoprecv(sc)) - ret = false; + if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) + fastcc = false; - if (!flush) { - if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ath_rx_tasklet(sc, 0, true); - ath_rx_tasklet(sc, 0, false); - } else { - ath_flushrecv(sc); - } + if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) + caldata = &sc->caldata; - return ret; -} + ath_dbg(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", + sc->sc_ah->curchan->channel, + channel->center_freq, conf_is_ht40(conf), + fastcc); -static bool ath_complete_reset(struct ath_softc *sc, bool start) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); + r = ath9k_hw_reset(ah, hchan, caldata, fastcc); + if (r) { + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); + goto ps_restore; + } if (ath_startrecv(sc) != 0) { ath_err(common, "Unable to restart recv logic\n"); - return false; + r = -EIO; + goto ps_restore; } ath9k_cmn_update_txpow(ah, sc->curtxpow, @@ -271,109 +296,21 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath9k_hw_set_interrupts(ah, ah->imask); ath9k_hw_enable_interrupts(ah); - if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) { + if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { if (sc->sc_flags & SC_OP_BEACONS) ath_set_beacon(sc); - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); if (!common->disable_ani) ath_start_ani(common); } - if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) { - struct ath_hw_antcomb_conf div_ant_conf; - u8 lna_conf; - - ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); - - if (sc->ant_rx == 1) - lna_conf = ATH_ANT_DIV_COMB_LNA1; - else - lna_conf = ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.main_lna_conf = lna_conf; - div_ant_conf.alt_lna_conf = lna_conf; - - ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); - } - - ieee80211_wake_queues(sc->hw); - - return true; -} - -static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, - bool retry_tx) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_cal_data *caldata = NULL; - bool fastcc = true; - bool flush = false; - int r; - - __ath_cancel_work(sc); - - spin_lock_bh(&sc->sc_pcu_lock); - - if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { - fastcc = false; - caldata = &sc->caldata; - } - - if (!hchan) { - fastcc = false; - flush = true; - hchan = ah->curchan; - } - - if (fastcc && !ath9k_hw_check_alive(ah)) - fastcc = false; - - if (!ath_prepare_reset(sc, retry_tx, flush)) - fastcc = false; - - ath_dbg(common, ATH_DBG_CONFIG, - "Reset to %u MHz, HT40: %d fastcc: %d\n", - hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS | - CHANNEL_HT40PLUS)), - fastcc); - - r = ath9k_hw_reset(ah, hchan, caldata, fastcc); - if (r) { - ath_err(common, - "Unable to reset channel, reset status %d\n", r); - goto out; - } - - if (!ath_complete_reset(sc, true)) - r = -EIO; + ps_restore: + ieee80211_wake_queues(hw); -out: spin_unlock_bh(&sc->sc_pcu_lock); - return r; -} - - -/* - * Set/change channels. If the channel is really being changed, it's done - * by reseting the chip. To accomplish this we must first cleanup any pending - * DMA, then restart stuff. -*/ -static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *hchan) -{ - int r; - - if (sc->sc_flags & SC_OP_INVALID) - return -EIO; - - ath9k_ps_wakeup(sc); - - r = ath_reset_internal(sc, hchan, false); ath9k_ps_restore(sc); - return r; } @@ -381,6 +318,7 @@ static void ath_paprd_activate(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_cal_data *caldata = ah->caldata; + struct ath_common *common = ath9k_hw_common(ah); int chain; if (!caldata || !caldata->paprd_done) @@ -389,7 +327,7 @@ static void ath_paprd_activate(struct ath_softc *sc) ath9k_ps_wakeup(sc); ar9003_paprd_enable(ah, false); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->txchainmask & BIT(chain))) + if (!(common->tx_chainmask & BIT(chain))) continue; ar9003_paprd_populate_single_table(ah, caldata, chain); @@ -476,7 +414,7 @@ void ath_paprd_calibrate(struct work_struct *work) memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->txchainmask & BIT(chain))) + if (!(common->tx_chainmask & BIT(chain))) continue; chain_ok = 0; @@ -597,7 +535,7 @@ void ath_ani_calibrate(unsigned long data) if (longcal || shortcal) { common->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, - ah->rxchainmask, longcal); + common->rx_chainmask, longcal); } ath9k_ps_restore(sc); @@ -608,7 +546,6 @@ void ath_ani_calibrate(unsigned long data) * The interval must be the shortest necessary to satisfy ANI, * short calibration and long calibration. */ - ath9k_debug_samp_bb_mac(sc); cal_interval = ATH_LONG_CALINTERVAL; if (sc->sc_ah->config.enable_ani) cal_interval = min(cal_interval, @@ -628,6 +565,7 @@ void ath_ani_calibrate(unsigned long data) static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an; + struct ath_hw *ah = sc->sc_ah; an = (struct ath_node *)sta->drv_priv; #ifdef CONFIG_ATH9K_DEBUGFS @@ -636,6 +574,9 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) spin_unlock(&sc->nodes_lock); an->sta = sta; #endif + if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) + sc->sc_flags |= SC_OP_ENABLE_APM; + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + @@ -659,6 +600,74 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) ath_tx_node_cleanup(sc, an); } +void ath_hw_check(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + unsigned long flags; + int busy; + + ath9k_ps_wakeup(sc); + if (ath9k_hw_check_alive(sc->sc_ah)) + goto out; + + spin_lock_irqsave(&common->cc_lock, flags); + busy = ath_update_survey_stats(sc); + spin_unlock_irqrestore(&common->cc_lock, flags); + + ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " + "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); + if (busy >= 99) { + if (++sc->hw_busy_count >= 3) { + spin_lock_bh(&sc->sc_pcu_lock); + ath_reset(sc, true); + spin_unlock_bh(&sc->sc_pcu_lock); + } + } else if (busy >= 0) + sc->hw_busy_count = 0; + +out: + ath9k_ps_restore(sc); +} + +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) +{ + static int count; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (pll_sqsum >= 0x40000) { + count++; + if (count == 3) { + /* Rx is hung for more than 500ms. Reset it */ + ath_dbg(common, ATH_DBG_RESET, + "Possible RX hang, resetting"); + spin_lock_bh(&sc->sc_pcu_lock); + ath_reset(sc, true); + spin_unlock_bh(&sc->sc_pcu_lock); + count = 0; + } + } else + count = 0; +} + +void ath_hw_pll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + hw_pll_work.work); + u32 pll_sqsum; + + if (AR_SREV_9485(sc->sc_ah)) { + + ath9k_ps_wakeup(sc); + pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); + ath9k_ps_restore(sc); + + ath_hw_pll_rx_hang_check(sc, pll_sqsum); + + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); + } +} + void ath9k_tasklet(unsigned long data) { @@ -671,7 +680,9 @@ void ath9k_tasklet(unsigned long data) if ((status & ATH9K_INT_FATAL) || (status & ATH9K_INT_BB_WATCHDOG)) { - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + spin_lock(&sc->sc_pcu_lock); + ath_reset(sc, true); + spin_unlock(&sc->sc_pcu_lock); return; } @@ -815,9 +826,11 @@ irqreturn_t ath_isr(int irq, void *dev) if (status & ATH9K_INT_TXURN) ath9k_hw_updatetxtriglevel(ah, true); - if (status & ATH9K_INT_RXEOL) { - ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); - ath9k_hw_set_interrupts(ah, ah->imask); + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { + if (status & ATH9K_INT_RXEOL) { + ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + ath9k_hw_set_interrupts(ah, ah->imask); + } } if (status & ATH9K_INT_MIB) { @@ -875,7 +888,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); atomic_set(&ah->intr_ref_cnt, -1); - ath9k_hw_configpcipowersave(ah, false); + ath9k_hw_configpcipowersave(ah, 0, 0); if (!ah->curchan) ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); @@ -887,13 +900,28 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) channel->center_freq, r); } - ath_complete_reset(sc, true); + ath9k_cmn_update_txpow(ah, sc->curtxpow, + sc->config.txpowlimit, &sc->curtxpow); + if (ath_startrecv(sc) != 0) { + ath_err(common, "Unable to restart recv logic\n"); + goto out; + } + if (sc->sc_flags & SC_OP_BEACONS) + ath_set_beacon(sc); /* restart beacons */ + + /* Re-Enable interrupts */ + ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); /* Enable LED */ ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(ah, ah->led_pin, 0); + ieee80211_wake_queues(hw); + ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2); + +out: spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); @@ -906,11 +934,12 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) int r; ath9k_ps_wakeup(sc); - - ath_cancel_work(sc); + cancel_delayed_work_sync(&sc->hw_pll_work); spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); + /* * Keep the LED on when the radio is disabled * during idle unassociated state. @@ -920,7 +949,13 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_hw_cfg_gpio_input(ah, ah->led_pin); } - ath_prepare_reset(sc, false, true); + /* Disable interrupts */ + ath9k_hw_disable_interrupts(ah); + + ath_drain_all_txq(sc, false); /* clear pending tx frames */ + + ath_stoprecv(sc); /* turn off frame recv */ + ath_flushrecv(sc); /* flush recv queue */ if (!ah->curchan) ah->curchan = ath9k_cmn_get_curchannel(hw, ah); @@ -934,19 +969,56 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_hw_phy_disable(ah); - ath9k_hw_configpcipowersave(ah, true); + ath9k_hw_configpcipowersave(ah, 1, 1); spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); } -static int ath_reset(struct ath_softc *sc, bool retry_tx) +int ath_reset(struct ath_softc *sc, bool retry_tx) { + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_hw *hw = sc->hw; int r; + sc->hw_busy_count = 0; + + /* Stop ANI */ + + del_timer_sync(&common->ani.timer); + ath9k_ps_wakeup(sc); - r = ath_reset_internal(sc, NULL, retry_tx); + ieee80211_stop_queues(hw); + + ath9k_hw_disable_interrupts(ah); + ath_drain_all_txq(sc, retry_tx); + + ath_stoprecv(sc); + ath_flushrecv(sc); + + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); + if (r) + ath_err(common, + "Unable to reset hardware; reset status %d\n", r); + + if (ath_startrecv(sc) != 0) + ath_err(common, "Unable to start recv logic\n"); + + /* + * We may be doing a reset in response to a request + * that changes the channel so update any state that + * might change as a result. + */ + ath9k_cmn_update_txpow(ah, sc->curtxpow, + sc->config.txpowlimit, &sc->curtxpow); + + if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) + ath_set_beacon(sc); /* restart beacons */ + + ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); if (retry_tx) { int i; @@ -959,80 +1031,15 @@ static int ath_reset(struct ath_softc *sc, bool retry_tx) } } - ath9k_ps_restore(sc); - - return r; -} - -void ath_reset_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); - - ath_reset(sc, true); -} - -void ath_hw_check(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - unsigned long flags; - int busy; - - ath9k_ps_wakeup(sc); - if (ath9k_hw_check_alive(sc->sc_ah)) - goto out; - - spin_lock_irqsave(&common->cc_lock, flags); - busy = ath_update_survey_stats(sc); - spin_unlock_irqrestore(&common->cc_lock, flags); - - ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " - "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); - if (busy >= 99) { - if (++sc->hw_busy_count >= 3) - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + ieee80211_wake_queues(hw); - } else if (busy >= 0) - sc->hw_busy_count = 0; + /* Start ANI */ + if (!common->disable_ani) + ath_start_ani(common); -out: ath9k_ps_restore(sc); -} - -static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) -{ - static int count; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - - if (pll_sqsum >= 0x40000) { - count++; - if (count == 3) { - /* Rx is hung for more than 500ms. Reset it */ - ath_dbg(common, ATH_DBG_RESET, - "Possible RX hang, resetting"); - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - count = 0; - } - } else - count = 0; -} - -void ath_hw_pll_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - hw_pll_work.work); - u32 pll_sqsum; - - if (AR_SREV_9485(sc->sc_ah)) { - - ath9k_ps_wakeup(sc); - pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); - ath9k_ps_restore(sc); - ath_hw_pll_rx_hang_check(sc, pll_sqsum); - - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); - } + return r; } /**********************/ @@ -1062,7 +1069,7 @@ static int ath9k_start(struct ieee80211_hw *hw) init_channel = ath9k_cmn_get_curchannel(hw, ah); /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(ah, false); + ath9k_hw_configpcipowersave(ah, 0, 0); /* * The basic interface to setting the hardware in a good @@ -1081,6 +1088,28 @@ static int ath9k_start(struct ieee80211_hw *hw) goto mutex_unlock; } + /* + * This is needed only to setup initial state + * but it's best done after a reset. + */ + ath9k_cmn_update_txpow(ah, sc->curtxpow, + sc->config.txpowlimit, &sc->curtxpow); + + /* + * Setup the hardware after reset: + * The receive engine is set going. + * Frame transmit is handled entirely + * in the frame output path; there's nothing to do + * here except setup the interrupt mask. + */ + if (ath_startrecv(sc) != 0) { + ath_err(common, "Unable to start recv logic\n"); + r = -EIO; + spin_unlock_bh(&sc->sc_pcu_lock); + goto mutex_unlock; + } + spin_unlock_bh(&sc->sc_pcu_lock); + /* Setup our intr mask. */ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ATH9K_INT_FATAL | @@ -1103,14 +1132,12 @@ static int ath9k_start(struct ieee80211_hw *hw) /* Disable BMISS interrupt when we're not associated */ ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); + ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); - if (!ath_complete_reset(sc, false)) { - r = -EIO; - spin_unlock_bh(&sc->sc_pcu_lock); - goto mutex_unlock; - } + ieee80211_wake_queues(hw); - spin_unlock_bh(&sc->sc_pcu_lock); + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && !ah->btcoex_hw.enabled) { @@ -1118,6 +1145,8 @@ static int ath9k_start(struct ieee80211_hw *hw) AR_STOMP_LOW_WLAN_WGHT); ath9k_hw_btcoex_enable(ah); + if (common->bus_ops->bt_coex_prep) + common->bus_ops->bt_coex_prep(common); if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) ath9k_btcoex_timer_resume(sc); } @@ -1203,7 +1232,10 @@ static void ath9k_stop(struct ieee80211_hw *hw) mutex_lock(&sc->mutex); - ath_cancel_work(sc); + cancel_delayed_work_sync(&sc->tx_complete_work); + cancel_delayed_work_sync(&sc->hw_pll_work); + cancel_work_sync(&sc->paprd_work); + cancel_work_sync(&sc->hw_check_work); if (sc->sc_flags & SC_OP_INVALID) { ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); @@ -1648,7 +1680,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel old_chan; int pos = curchan->hw_value; int old_pos = -1; unsigned long flags; @@ -1665,24 +1696,14 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) "Set channel: %d MHz type: %d\n", curchan->center_freq, conf->channel_type); + ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], + curchan, conf->channel_type); + /* update survey stats for the old channel before switching */ spin_lock_irqsave(&common->cc_lock, flags); ath_update_survey_stats(sc); spin_unlock_irqrestore(&common->cc_lock, flags); - /* - * Preserve the current channel values, before updating - * the same channel - */ - if (old_pos == pos) { - memcpy(&old_chan, &sc->sc_ah->channels[pos], - sizeof(struct ath9k_channel)); - ah->curchan = &old_chan; - } - - ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], - curchan, conf->channel_type); - /* * If the operating channel changes, change the survey in-use flags * along with it. @@ -2314,11 +2335,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) ath9k_ps_wakeup(sc); spin_lock_bh(&sc->sc_pcu_lock); drain_txq = ath_drain_all_txq(sc, false); - spin_unlock_bh(&sc->sc_pcu_lock); - if (!drain_txq) ath_reset(sc, false); - + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); ieee80211_wake_queues(hw); @@ -2381,73 +2400,6 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) return sc->beacon.tx_last; } -static int ath9k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; - - stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; - stats->dot11RTSFailureCount = mib_stats->rts_bad; - stats->dot11FCSErrorCount = mib_stats->fcs_bad; - stats->dot11RTSSuccessCount = mib_stats->rts_good; - return 0; -} - -static u32 fill_chainmask(u32 cap, u32 new) -{ - u32 filled = 0; - int i; - - for (i = 0; cap && new; i++, cap >>= 1) { - if (!(cap & BIT(0))) - continue; - - if (new & BIT(0)) - filled |= BIT(i); - - new >>= 1; - } - - return filled; -} - -static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - - if (!rx_ant || !tx_ant) - return -EINVAL; - - sc->ant_rx = rx_ant; - sc->ant_tx = tx_ant; - - if (ah->caps.rx_chainmask == 1) - return 0; - - /* AR9100 runs into calibration issues if not all rx chains are enabled */ - if (AR_SREV_9100(ah)) - ah->rxchainmask = 0x7; - else - ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant); - - ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant); - ath9k_reload_chainmask_settings(sc); - - return 0; -} - -static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) -{ - struct ath_softc *sc = hw->priv; - - *tx_ant = sc->ant_tx; - *rx_ant = sc->ant_rx; - return 0; -} - struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2472,8 +2424,5 @@ struct ieee80211_ops ath9k_ops = { .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, .tx_frames_pending = ath9k_tx_frames_pending, - .tx_last_beacon = ath9k_tx_last_beacon, - .get_stats = ath9k_get_stats, - .set_antenna = ath9k_set_antenna, - .get_antenna = ath9k_get_antenna, + .tx_last_beacon = ath9k_tx_last_beacon, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index 891661a61513..5685cf11cfe3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -32,11 +32,9 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ - { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { 0 } }; - /* return bus cachesize in 4B word units */ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) { @@ -90,6 +88,23 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) return true; } +/* + * Bluetooth coexistance requires disabling ASPM. + */ +static void ath_pci_bt_coex_prep(struct ath_common *common) +{ + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct pci_dev *pdev = to_pci_dev(sc->dev); + u8 aspm; + + if (!pci_is_pcie(pdev)) + return; + + pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); + aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); + pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); +} + static void ath_pci_extn_synch_enable(struct ath_common *common) { struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -101,7 +116,6 @@ static void ath_pci_extn_synch_enable(struct ath_common *common) pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl); } -/* Need to be called after we discover btcoex capabilities */ static void ath_pci_aspm_init(struct ath_common *common) { struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -111,38 +125,19 @@ static void ath_pci_aspm_init(struct ath_common *common) int pos; u8 aspm; - pos = pci_pcie_cap(pdev); - if (!pos) + if (!pci_is_pcie(pdev)) return; parent = pdev->bus->self; - if (!parent) + if (WARN_ON(!parent)) return; - if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) { - /* Bluetooth coexistance requires disabling ASPM. */ - pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); - aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); - pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); - - /* - * Both upstream and downstream PCIe components should - * have the same ASPM settings. - */ - pos = pci_pcie_cap(parent); - pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); - aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); - pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); - - return; - } - pos = pci_pcie_cap(parent); pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { ah->aspm_enabled = true; /* Initialize PCIe PM and SERDES registers. */ - ath9k_hw_configpcipowersave(ah, false); + ath9k_hw_configpcipowersave(ah, 0, 0); } } @@ -150,6 +145,7 @@ static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath_pci_read_cachesize, .eeprom_read = ath_pci_eeprom_read, + .bt_coex_prep = ath_pci_bt_coex_prep, .extn_synch_en = ath_pci_extn_synch_enable, .aspm_init = ath_pci_aspm_init, }; @@ -342,7 +338,7 @@ static int ath_pci_resume(struct device *device) * semi-random values after suspend/resume. */ ath9k_ps_wakeup(sc); - ath9k_cmn_init_crypto(sc->sc_ah); + ath9k_init_crypto(sc); ath9k_ps_restore(sc); sc->ps_idle = true; diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index 4f1301881137..9e3649a3d5ca 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -603,8 +603,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, static u8 ath_rc_get_highest_rix(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, const struct ath_rate_table *rate_table, - int *is_probing, - bool legacy) + int *is_probing) { u32 best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; @@ -625,8 +624,6 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, u8 per_thres; rate = ath_rc_priv->valid_rate_index[index]; - if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY)) - continue; if (rate > ath_rc_priv->rate_max_phy) continue; @@ -770,7 +767,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate *rates = tx_info->control.rates; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; - u8 try_per_rate, i = 0, rix, high_rix; + u8 try_per_rate, i = 0, rix; int is_probe = 0; if (rate_control_send_low(sta, priv_sta, txrc)) @@ -789,9 +786,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate = 4; rate_table = ath_rc_priv->rate_table; - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, - &is_probe, false); - high_rix = rix; + rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); /* * If we're in HT mode and both us and our peer supports LDPC. @@ -827,7 +822,10 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, } /* Fill in the other rates for multirate retry */ - for ( ; i < 3; i++) { + for ( ; i < 4; i++) { + /* Use twice the number of tries for the last MRR segment. */ + if (i + 1 == 4) + try_per_rate = 8; ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); /* All other rates in the series have RTS enabled */ @@ -835,24 +833,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate, rix, 1); } - /* Use twice the number of tries for the last MRR segment. */ - try_per_rate = 8; - - /* - * Use a legacy rate as last retry to ensure that the frame - * is tried in both MCS and legacy rates. - */ - if ((rates[2].flags & IEEE80211_TX_RC_MCS) && - (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) || - (ath_rc_priv->per[high_rix] > 45))) - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, - &is_probe, true); - else - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); - - /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_per_rate, rix, 1); /* * NB:Change rate series to enable aggregation when operating * at lower MCS rates. When first rate in series is MCS2 diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 8d3e19dfe7db..74094022b654 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -761,7 +761,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, * on. All this is necessary because of our use of * a self-linked list to avoid rx overruns. */ - ret = ath9k_hw_rxprocdesc(ah, ds, rs); + ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0); if (ret == -EINPROGRESS) { struct ath_rx_status trs; struct ath_buf *tbf; @@ -787,7 +787,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, */ tds = tbf->bf_desc; - ret = ath9k_hw_rxprocdesc(ah, tds, &trs); + ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); if (ret == -EINPROGRESS) return NULL; } @@ -824,8 +824,7 @@ static bool ath9k_rx_accept(struct ath_common *common, is_mc = !!is_multicast_ether_addr(hdr->addr1); is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && test_bit(rx_stats->rs_keyix, common->tkip_keymap); - strip_mic = is_valid_tkip && ieee80211_is_data(fc) && - !(rx_stats->rs_status & + strip_mic = is_valid_tkip && !(rx_stats->rs_status & (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC)); if (!rx_stats->rs_datalen) @@ -937,7 +936,7 @@ static int ath9k_process_rate(struct ath_common *common, * No valid hardware bitrate found -- we should not get here * because hardware has already validated this frame as OK. */ - ath_dbg(common, ATH_DBG_ANY, + ath_dbg(common, ATH_DBG_XMIT, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", rx_stats->rs_rate); @@ -952,12 +951,23 @@ static void ath9k_process_rssi(struct ath_common *common, struct ath_softc *sc = hw->priv; struct ath_hw *ah = common->ah; int last_rssi; + __le16 fc; - if (!rx_stats->is_mybeacon || - ((ah->opmode != NL80211_IFTYPE_STATION) && - (ah->opmode != NL80211_IFTYPE_ADHOC))) + if ((ah->opmode != NL80211_IFTYPE_STATION) && + (ah->opmode != NL80211_IFTYPE_ADHOC)) return; + fc = hdr->frame_control; + if (!ieee80211_is_beacon(fc) || + compare_ether_addr(hdr->addr3, common->curbssid)) { + /* TODO: This doesn't work well if you have stations + * associated to two different APs because curbssid + * is just the last AP that any of the stations associated + * with. + */ + return; + } + if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); @@ -1827,11 +1837,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); rxs = IEEE80211_SKB_RXCB(hdr_skb); - if (ieee80211_is_beacon(hdr->frame_control) && - !compare_ether_addr(hdr->addr3, common->curbssid)) - rs.is_mybeacon = true; - else - rs.is_mybeacon = false; ath_debug_stat_rx(sc, &rs); @@ -1950,7 +1955,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) + if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) ath_ant_comb_scan(sc, &rs); ieee80211_rx(hw, skb); @@ -1973,10 +1978,5 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) spin_unlock_bh(&sc->rx.rxbuflock); - if (!(ah->imask & ATH9K_INT_RXEOL)) { - ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); - ath9k_hw_set_interrupts(ah, ah->imask); - } - return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 5d34381c44c3..fa4c0bbce6b9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -619,7 +619,6 @@ #define AR_D_GBL_IFS_EIFS 0x10b0 #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 -#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363 #define AR_D_GBL_IFS_MISC 0x10f0 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 @@ -794,8 +793,6 @@ #define AR_SREV_REVISION_9485_10 0 #define AR_SREV_REVISION_9485_11 1 #define AR_SREV_VERSION_9340 0x300 -#define AR_SREV_VERSION_9580 0x1C0 -#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -896,18 +893,6 @@ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) -#define AR_SREV_9580(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) - -#define AR_SREV_9580_10(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10)) - -/* NOTE: When adding chips newer than Peacock, add chip check here */ -#define AR_SREV_9580_10_OR_LATER(_ah) \ - (AR_SREV_9580(_ah)) - enum ath_usb_dev { AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ @@ -1132,7 +1117,7 @@ enum { #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) #define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 -#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000 +#define AR_ENT_OTP_MPSD 0x00800000 #define AR_CH0_BB_DPLL1 0x16180 #define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 @@ -1504,7 +1489,6 @@ enum { #define AR_USEC_TX_LAT_S 14 #define AR_USEC_RX_LAT 0x1F800000 #define AR_USEC_RX_LAT_S 23 -#define AR_USEC_ASYNC_FIFO 0x12E00074 #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index cb37047e71d2..e815e825e9cb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -48,9 +48,8 @@ static u16 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb); -static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - int tx_flags, struct ath_txq *txq); + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); @@ -62,10 +61,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); -static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid, - struct sk_buff *skb); enum { MCS_HT20, @@ -134,7 +129,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) spin_lock_bh(&txq->axq_lock); tid->paused = false; - if (skb_queue_empty(&tid->buf_q)) + if (list_empty(&tid->buf_q)) goto unlock; ath_tx_queue_tid(txq, tid); @@ -154,7 +149,6 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { struct ath_txq *txq = tid->ac->txq; - struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -165,17 +159,17 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) memset(&ts, 0, sizeof(ts)); spin_lock_bh(&txq->axq_lock); - while ((skb = __skb_dequeue(&tid->buf_q))) { - fi = get_frame_info(skb); - bf = fi->bf; + while (!list_empty(&tid->buf_q)) { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); spin_unlock_bh(&txq->axq_lock); - if (bf && fi->retries) { - list_add_tail(&bf->list, &bf_head); - ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); } else { - ath_tx_send_normal(sc, txq, NULL, skb); + ath_tx_send_normal(sc, txq, NULL, &bf_head); } spin_lock_bh(&txq->axq_lock); } @@ -225,7 +219,6 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid) { - struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -234,21 +227,16 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); - while ((skb = __skb_dequeue(&tid->buf_q))) { - fi = get_frame_info(skb); - bf = fi->bf; - - if (!bf) { - spin_unlock(&txq->axq_lock); - ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); - spin_lock(&txq->axq_lock); - continue; - } + for (;;) { + if (list_empty(&tid->buf_q)) + break; - list_add_tail(&bf->list, &bf_head); + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); + fi = get_frame_info(bf->bf_mpdu); if (fi->retries) - ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -338,7 +326,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, while (bf) { fi = get_frame_info(bf->bf_mpdu); - ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno); + ba_index = ATH_BA_INDEX(seq_st, fi->seqno); (*nframes)++; if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) @@ -361,8 +349,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ieee80211_tx_info *tx_info; struct ath_atx_tid *tid = NULL; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct list_head bf_head; - struct sk_buff_head bf_pending; + struct list_head bf_head, bf_pending; u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; @@ -435,12 +422,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } } - __skb_queue_head_init(&bf_pending); + INIT_LIST_HEAD(&bf_pending); + INIT_LIST_HEAD(&bf_head); ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { - u16 seqno = bf->bf_state.seqno; - txfail = txpending = sendbar = 0; bf_next = bf->bf_next; @@ -448,7 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@ -481,10 +467,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Make sure the last desc is reclaimed if it * not a holding desc. */ - INIT_LIST_HEAD(&bf_head); - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || - bf_next != NULL || !bf_last->bf_stale) + if (!bf_last->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); + else + INIT_LIST_HEAD(&bf_head); if (!txpending || (tid->state & AGGR_CLEANUP)) { /* @@ -492,7 +478,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { @@ -520,7 +506,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= @@ -535,7 +521,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - fi->bf = tbf; + list_add_tail(&tbf->list, &bf_head); } else { /* * Clear descriptor status words for @@ -550,23 +536,22 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Put this buffer to the temporary pending * queue to retain ordering */ - __skb_queue_tail(&bf_pending, skb); + list_splice_tail_init(&bf_head, &bf_pending); } bf = bf_next; } /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!skb_queue_empty(&bf_pending)) { + if (!list_empty(&bf_pending)) { if (an->sleeping) ieee80211_sta_set_tim(sta); spin_lock_bh(&txq->axq_lock); if (clear_filter) tid->ac->clear_ps_filter = true; - skb_queue_splice(&bf_pending, &tid->buf_q); - if (!an->sleeping) - ath_tx_queue_tid(txq, tid); + list_splice(&bf_pending, &tid->buf_q); + ath_tx_queue_tid(txq, tid); spin_unlock_bh(&txq->axq_lock); } @@ -582,29 +567,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, rcu_read_unlock(); if (needreset) - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); -} - -static bool ath_lookup_legacy(struct ath_buf *bf) -{ - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - int i; - - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - - for (i = 0; i < 4; i++) { - if (!rates[i].count || rates[i].idx < 0) - break; - - if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) - return true; - } - - return false; + ath_reset(sc, false); } static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, @@ -680,10 +643,8 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, * meet the minimum required mpdudensity. */ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, u16 frmlen, - bool first_subfrm) + struct ath_buf *bf, u16 frmlen) { -#define FIRST_DESC_NDELIMS 60 struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); u32 nsymbits, nsymbols; @@ -705,14 +666,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) ndelim += ATH_AGGR_ENCRYPTDELIM; - /* - * Add delimiter when using RTS/CTS with aggregation - * and non enterprise AR9003 card - */ - if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) && - (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE)) - ndelim = max(ndelim, FIRST_DESC_NDELIMS); - /* * Convert desired mpdu density from microeconds to bytes based * on highest rate in rate series (i.e. first rate) to determine @@ -758,33 +711,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; + struct ath_buf *bf, *bf_first, *bf_prev = NULL; int rl = 0, nframes = 0, ndelim, prev_al = 0; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; - struct sk_buff *skb; - u16 seqno; - do { - skb = skb_peek(&tid->buf_q); - fi = get_frame_info(skb); - bf = fi->bf; - if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); + bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); - if (!bf) - continue; - - bf->bf_state.bf_type |= BUF_AMPDU; - seqno = bf->bf_state.seqno; - if (!bf_first) - bf_first = bf; + do { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + fi = get_frame_info(bf->bf_mpdu); /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@ -798,8 +740,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; if (nframes && - ((aggr_limit < (al + bpad + al_delta + prev_al)) || - ath_lookup_legacy(bf))) { + (aggr_limit < (al + bpad + al_delta + prev_al))) { status = ATH_AGGR_LIMITED; break; } @@ -814,6 +755,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, status = ATH_AGGR_LIMITED; break; } + nframes++; /* add padding for previous frame to aggregation length */ al += bpad + al_delta; @@ -822,21 +764,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, * Get the delimiters needed to meet the MPDU * density for this node. */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen, - !nframes); + ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); bpad = PADBYTES(al_delta) + (ndelim << 2); - nframes++; bf->bf_next = NULL; ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); /* link buffers of this frame to the aggregate */ if (!fi->retries) - ath_tx_addto_baw(sc, tid, seqno); + ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); - - __skb_unlink(skb, &tid->buf_q); - list_add_tail(&bf->list, bf_q); + list_move_tail(&bf->list, bf_q); if (bf_prev) { bf_prev->bf_next = bf; ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, @@ -844,7 +782,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } bf_prev = bf; - } while (!skb_queue_empty(&tid->buf_q)); + } while (!list_empty(&tid->buf_q)); *aggr_len = al; @@ -862,7 +800,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, int aggr_len; do { - if (skb_queue_empty(&tid->buf_q)) + if (list_empty(&tid->buf_q)) return; INIT_LIST_HEAD(&bf_q); @@ -983,7 +921,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); - if (!skb_queue_empty(&tid->buf_q)) + if (!list_empty(&tid->buf_q)) buffered = true; tid->sched = false; @@ -1016,7 +954,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); ac->clear_ps_filter = true; - if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { + if (!list_empty(&tid->buf_q) && !tid->paused) { ath_tx_queue_tid(txq, tid); ath_txq_schedule(sc, txq); } @@ -1333,7 +1271,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) struct ath_atx_ac *ac, *ac_tmp, *last_ac; struct ath_atx_tid *tid, *last_tid; - if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) || + if (list_empty(&txq->axq_acq) || txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) return; @@ -1360,7 +1298,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) * add tid to round-robin queue if more frames * are pending for the tid */ - if (!skb_queue_empty(&tid->buf_q)) + if (!list_empty(&tid->buf_q)) ath_tx_queue_tid(txq, tid); if (tid == last_tid || @@ -1452,11 +1390,12 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct sk_buff *skb, struct ath_tx_control *txctl) + struct ath_buf *bf, struct ath_tx_control *txctl) { - struct ath_frame_info *fi = get_frame_info(skb); + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); struct list_head bf_head; - struct ath_buf *bf; + + bf->bf_state.bf_type |= BUF_AMPDU; /* * Do not queue to h/w when any of the following conditions is true: @@ -1465,30 +1404,25 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - seqno is not within block-ack window * - h/w queue depth exceeds low water mark */ - if (!skb_queue_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || + if (!list_empty(&tid->buf_q) || tid->paused || + !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); - __skb_queue_tail(&tid->buf_q, skb); - if (!txctl->an || !txctl->an->sleeping) - ath_tx_queue_tid(txctl->txq, tid); + list_add_tail(&bf->list, &tid->buf_q); + ath_tx_queue_tid(txctl->txq, tid); return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); - if (!bf) - return; - - bf->bf_state.bf_type |= BUF_AMPDU; INIT_LIST_HEAD(&bf_head); list_add(&bf->list, &bf_head); /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); /* Queue to h/w without aggregation */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); @@ -1498,21 +1432,13 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, } static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb) + struct ath_atx_tid *tid, + struct list_head *bf_head) { - struct ath_frame_info *fi = get_frame_info(skb); - struct list_head bf_head; + struct ath_frame_info *fi; struct ath_buf *bf; - bf = fi->bf; - if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); - - if (!bf) - return; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); + bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ @@ -1520,8 +1446,9 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; + fi = get_frame_info(bf->bf_mpdu); ath_buf_set_rate(sc, bf, fi->framelen); - ath_tx_txqaddbuf(sc, txq, &bf_head, false); + ath_tx_txqaddbuf(sc, txq, bf_head, false); TX_STAT_INC(txq->axq_qnum, queued); } @@ -1551,19 +1478,39 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, int framelen) { + struct ath_softc *sc = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr; struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an = NULL; + struct ath_atx_tid *tid; enum ath9k_key_type keytype; + u16 seqno = 0; + u8 tidno; keytype = ath9k_cmn_get_hw_crypto_keytype(skb); if (sta) an = (struct ath_node *) sta->drv_priv; + hdr = (struct ieee80211_hdr *)skb->data; + if (an && ieee80211_is_data_qos(hdr->frame_control) && + conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { + + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + + /* + * Override seqno set by upper layer with the one + * in tx aggregation state. + */ + tid = ATH_AN_2_TID(an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); + } + memset(fi, 0, sizeof(*fi)); if (hw_key) fi->keyix = hw_key->hw_key_idx; @@ -1573,6 +1520,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; fi->framelen = framelen; + fi->seqno = seqno; } static int setup_tx_flags(struct sk_buff *skb) @@ -1624,9 +1572,9 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) { struct ath_hw *ah = sc->sc_ah; struct ath9k_channel *curchan = ah->curchan; - if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && - (curchan->channelFlags & CHANNEL_5GHZ) && - (chainmask == 0x7) && (rate < 0x90)) + if ((sc->sc_flags & SC_OP_ENABLE_APM) && + (curchan->channelFlags & CHANNEL_5GHZ) && + (chainmask == 0x7) && (rate < 0x90)) return 0x3; else return chainmask; @@ -1634,7 +1582,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) { - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_11n_rate_series series[4]; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; @@ -1694,7 +1642,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) /* MCS rates */ series[i].Rate = rix | 0x80; series[i].ChSel = ath_txchainmask_reduction(sc, - ah->txchainmask, series[i].Rate); + common->tx_chainmask, series[i].Rate); series[i].PktDuration = ath_pkt_duration(sc, rix, len, is_40, is_sgi, is_sp); if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) @@ -1719,10 +1667,10 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) } if (bf->bf_state.bfs_paprd) - series[i].ChSel = ah->txchainmask; + series[i].ChSel = common->tx_chainmask; else series[i].ChSel = ath_txchainmask_reduction(sc, - ah->txchainmask, series[i].Rate); + common->tx_chainmask, series[i].Rate); series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, phy, rate->bitrate * 100, len, rix, is_sp); @@ -1744,39 +1692,26 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) } -/* - * Assign a descriptor (and sequence number if necessary, - * and map buffer for DMA. Frees skb on error - */ -static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, +static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb) { + struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_buf *bf; struct ath_desc *ds; int frm_type; - u16 seqno; bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); - goto error; + return NULL; } ATH_TXBUF_RESET(bf); - if (tid) { - seqno = tid->seq_next; - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - bf->bf_state.seqno = seqno; - } - bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; @@ -1788,7 +1723,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - goto error; + return NULL; } frm_type = get_hw_packet_type(skb); @@ -1807,23 +1742,19 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf->bf_buf_addr, txq->axq_qnum); - fi->bf = bf; return bf; - -error: - dev_kfree_skb_any(skb); - return NULL; } /* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_control *txctl) { + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct list_head bf_head; struct ath_atx_tid *tid = NULL; - struct ath_buf *bf; u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); @@ -1841,11 +1772,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, * Try aggregation if it's a unicast data frame * and the destination is HT capable. */ - ath_tx_send_ampdu(sc, tid, skb, txctl); + ath_tx_send_ampdu(sc, tid, bf, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); - if (!bf) - goto out; + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); bf->bf_state.bfs_paprd = txctl->paprd; @@ -1859,10 +1789,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); - ath_tx_send_normal(sc, txctl->txq, tid, skb); + ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } -out: spin_unlock_bh(&txctl->txq->axq_lock); } @@ -1876,6 +1805,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; struct ath_txq *txq = txctl->txq; + struct ath_buf *bf; int padpos, padsize; int frmlen = skb->len + FCS_LEN; int q; @@ -1922,6 +1852,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, * info are no longer valid (overwritten by the ath_frame_info data. */ + bf = ath_tx_setup_buffer(hw, txctl->txq, skb); + if (unlikely(!bf)) + return -ENOMEM; + q = skb_get_queue_mapping(skb); spin_lock_bh(&txq->axq_lock); if (txq == sc->tx.txq_map[q] && @@ -1931,7 +1865,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, } spin_unlock_bh(&txq->axq_lock); - ath_tx_start_dma(sc, skb, txctl); + ath_tx_start_dma(sc, bf, txctl); + return 0; } @@ -2148,9 +2083,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) spin_lock_bh(&txq->axq_lock); for (;;) { - if (work_pending(&sc->hw_reset_work)) - break; - if (list_empty(&txq->axq_q)) { txq->axq_link = NULL; if (sc->sc_flags & SC_OP_TXAGGR) @@ -2238,7 +2170,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) if (needreset) { ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, "tx hung, resetting the chip\n"); - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + spin_lock_bh(&sc->sc_pcu_lock); + ath_reset(sc, true); + spin_unlock_bh(&sc->sc_pcu_lock); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@ -2271,9 +2205,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) int status; for (;;) { - if (work_pending(&sc->hw_reset_work)) - break; - status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); if (status == -EINPROGRESS) break; @@ -2428,7 +2359,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->sched = false; tid->paused = false; tid->state &= ~AGGR_CLEANUP; - __skb_queue_head_init(&tid->buf_q); + INIT_LIST_HEAD(&tid->buf_q); acno = TID_TO_WME_AC(tidno); tid->ac = &an->ac[acno]; tid->state &= ~AGGR_ADDBA_COMPLETE; diff --git a/trunk/drivers/net/wireless/ath/carl9170/Kconfig b/trunk/drivers/net/wireless/ath/carl9170/Kconfig index 267d5dcf82dc..2d1b821b440d 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/Kconfig +++ b/trunk/drivers/net/wireless/ath/carl9170/Kconfig @@ -39,17 +39,3 @@ config CARL9170_WPC bool depends on CARL9170 && (INPUT = y || INPUT = CARL9170) default y - -config CARL9170_HWRNG - bool "Random number generator" - depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170) - default n - help - Provides a hardware random number generator to the kernel. - - SECURITY WARNING: It's relatively easy to eavesdrop all - generated random numbers from the transport stream with - usbmon [software] or special usb sniffer hardware. - - Say N, unless your setup[i.e.: embedded system] has no - other rng source and you can afford to take the risk. diff --git a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h index 6cfbb419e2f6..c5427a72a1e2 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -152,7 +151,6 @@ struct carl9170_sta_tid { #define CARL9170_TX_TIMEOUT 2500 #define CARL9170_JANITOR_DELAY 128 #define CARL9170_QUEUE_STUCK_TIMEOUT 5500 -#define CARL9170_STAT_WORK 30000 #define CARL9170_NUM_TX_AGG_MAX 30 @@ -284,7 +282,6 @@ struct ar9170 { bool rx_stream; bool tx_stream; bool rx_filter; - bool hw_counters; unsigned int mem_blocks; unsigned int mem_block_size; unsigned int rx_size; @@ -334,21 +331,11 @@ struct ar9170 { /* PHY */ struct ieee80211_channel *channel; - unsigned int num_channels; int noise[4]; unsigned int chan_fail; unsigned int total_chan_fail; u8 heavy_clip; u8 ht_settings; - struct { - u64 active; /* usec */ - u64 cca; /* usec */ - u64 tx_time; /* usec */ - u64 rx_total; - u64 rx_overrun; - } tally; - struct delayed_work stat_work; - struct survey_info *survey; /* power calibration data */ u8 power_5G_leg[4]; @@ -450,17 +437,6 @@ struct ar9170 { unsigned int off_override; bool state; } ps; - -#ifdef CONFIG_CARL9170_HWRNG -# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN - struct { - struct hwrng rng; - bool initialized; - char name[30 + 1]; - u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)]; - unsigned int cache_idx; - } rng; -#endif /* CONFIG_CARL9170_HWRNG */ }; enum carl9170_ps_off_override_reasons { diff --git a/trunk/drivers/net/wireless/ath/carl9170/cmd.c b/trunk/drivers/net/wireless/ath/carl9170/cmd.c index 195dc6538110..cdfc94c371b4 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/cmd.c +++ b/trunk/drivers/net/wireless/ath/carl9170/cmd.c @@ -36,7 +36,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include "carl9170.h" #include "cmd.h" @@ -166,39 +165,6 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, return __carl9170_exec_cmd(ar, cmd, true); } -int carl9170_collect_tally(struct ar9170 *ar) -{ - struct carl9170_tally_rsp tally; - struct survey_info *info; - unsigned int tick; - int err; - - err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL, - sizeof(tally), (u8 *)&tally); - if (err) - return err; - - tick = le32_to_cpu(tally.tick); - if (tick) { - ar->tally.active += le32_to_cpu(tally.active) / tick; - ar->tally.cca += le32_to_cpu(tally.cca) / tick; - ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick; - ar->tally.rx_total += le32_to_cpu(tally.rx_total); - ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun); - - if (ar->channel) { - info = &ar->survey[ar->channel->hw_value]; - info->channel_time = ar->tally.active; - info->channel_time_busy = ar->tally.cca; - info->channel_time_tx = ar->tally.tx_time; - do_div(info->channel_time, 1000); - do_div(info->channel_time_busy, 1000); - do_div(info->channel_time_tx, 1000); - } - } - return 0; -} - int carl9170_powersave(struct ar9170 *ar, const bool ps) { struct carl9170_cmd *cmd; diff --git a/trunk/drivers/net/wireless/ath/carl9170/cmd.h b/trunk/drivers/net/wireless/ath/carl9170/cmd.h index 885c42778b8b..d5f95bdc75c1 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/cmd.h +++ b/trunk/drivers/net/wireless/ath/carl9170/cmd.h @@ -50,7 +50,6 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v); int carl9170_reboot(struct ar9170 *ar); int carl9170_mac_reset(struct ar9170 *ar); int carl9170_powersave(struct ar9170 *ar, const bool power_on); -int carl9170_collect_tally(struct ar9170 *ar); int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, const u32 mode, const u32 addr, const u32 len); diff --git a/trunk/drivers/net/wireless/ath/carl9170/fw.c b/trunk/drivers/net/wireless/ath/carl9170/fw.c index f4cae1cccbff..39ddea5794f7 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/fw.c +++ b/trunk/drivers/net/wireless/ath/carl9170/fw.c @@ -266,9 +266,6 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) FIF_PROMISC_IN_BSS; } - if (SUPP(CARL9170FW_HW_COUNTERS)) - ar->fw.hw_counters = true; - if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); diff --git a/trunk/drivers/net/wireless/ath/carl9170/fwcmd.h b/trunk/drivers/net/wireless/ath/carl9170/fwcmd.h index 9443c802b25b..0a6dec529b59 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/trunk/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -55,7 +55,6 @@ enum carl9170_cmd_oids { CARL9170_CMD_READ_TSF = 0x06, CARL9170_CMD_RX_FILTER = 0x07, CARL9170_CMD_WOL = 0x08, - CARL9170_CMD_TALLY = 0x09, /* CAM */ CARL9170_CMD_EKEY = 0x10, @@ -287,15 +286,6 @@ struct carl9170_tsf_rsp { } __packed; #define CARL9170_TSF_RSP_SIZE 8 -struct carl9170_tally_rsp { - __le32 active; - __le32 cca; - __le32 tx_time; - __le32 rx_total; - __le32 rx_overrun; - __le32 tick; -} __packed; - struct carl9170_rsp { struct carl9170_cmd_head hdr; @@ -310,7 +300,6 @@ struct carl9170_rsp { struct carl9170_gpio gpio; struct carl9170_tsf_rsp tsf; struct carl9170_psm psm; - struct carl9170_tally_rsp tally; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; } __packed; } __packed __aligned(4); diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index 782b8f3ae58f..0122930b14c7 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -413,9 +413,6 @@ static int carl9170_op_start(struct ieee80211_hw *hw) carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); - ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, - round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); - ieee80211_wake_queues(ar->hw); err = 0; @@ -426,7 +423,6 @@ static int carl9170_op_start(struct ieee80211_hw *hw) static void carl9170_cancel_worker(struct ar9170 *ar) { - cancel_delayed_work_sync(&ar->stat_work); cancel_delayed_work_sync(&ar->tx_janitor); #ifdef CONFIG_CARL9170_LEDS cancel_delayed_work_sync(&ar->led_work); @@ -798,43 +794,6 @@ static void carl9170_ps_work(struct work_struct *work) mutex_unlock(&ar->mutex); } -static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise) -{ - int err; - - if (noise) { - err = carl9170_get_noisefloor(ar); - if (err) - return err; - } - - if (ar->fw.hw_counters) { - err = carl9170_collect_tally(ar); - if (err) - return err; - } - - if (flush) - memset(&ar->tally, 0, sizeof(ar->tally)); - - return 0; -} - -static void carl9170_stat_work(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work); - int err; - - mutex_lock(&ar->mutex); - err = carl9170_update_survey(ar, false, true); - mutex_unlock(&ar->mutex); - - if (err) - return; - - ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, - round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); -} static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) { @@ -869,19 +828,11 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) if (err) goto out; - err = carl9170_update_survey(ar, true, false); - if (err) - goto out; - err = carl9170_set_channel(ar, hw->conf.channel, hw->conf.channel_type, CARL9170_RFI_NONE); if (err) goto out; - err = carl9170_update_survey(ar, false, true); - if (err) - goto out; - err = carl9170_set_dyn_sifs_ack(ar); if (err) goto out; @@ -1468,159 +1419,24 @@ static int carl9170_register_wps_button(struct ar9170 *ar) } #endif /* CONFIG_CARL9170_WPC */ -#ifdef CONFIG_CARL9170_HWRNG -static int carl9170_rng_get(struct ar9170 *ar) +static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) { - -#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32)) -#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN) - - static const __le32 rng_load[RW] = { - [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)}; - - u32 buf[RW]; - - unsigned int i, off = 0, transfer, count; + struct ar9170 *ar = hw->priv; int err; - BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN); - - if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized) - return -EAGAIN; - - count = ARRAY_SIZE(ar->rng.cache); - while (count) { - err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, - RB, (u8 *) rng_load, - RB, (u8 *) buf); - if (err) - return err; - - transfer = min_t(unsigned int, count, RW); - for (i = 0; i < transfer; i++) - ar->rng.cache[off + i] = buf[i]; - - off += transfer; - count -= transfer; - } - - ar->rng.cache_idx = 0; - -#undef RW -#undef RB - return 0; -} - -static int carl9170_rng_read(struct hwrng *rng, u32 *data) -{ - struct ar9170 *ar = (struct ar9170 *)rng->priv; - int ret = -EIO; + if (idx != 0) + return -ENOENT; mutex_lock(&ar->mutex); - if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) { - ret = carl9170_rng_get(ar); - if (ret) { - mutex_unlock(&ar->mutex); - return ret; - } - } - - *data = ar->rng.cache[ar->rng.cache_idx++]; + err = carl9170_get_noisefloor(ar); mutex_unlock(&ar->mutex); - - return sizeof(u16); -} - -static void carl9170_unregister_hwrng(struct ar9170 *ar) -{ - if (ar->rng.initialized) { - hwrng_unregister(&ar->rng.rng); - ar->rng.initialized = false; - } -} - -static int carl9170_register_hwrng(struct ar9170 *ar) -{ - int err; - - snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name), - "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy)); - ar->rng.rng.name = ar->rng.name; - ar->rng.rng.data_read = carl9170_rng_read; - ar->rng.rng.priv = (unsigned long)ar; - - if (WARN_ON(ar->rng.initialized)) - return -EALREADY; - - err = hwrng_register(&ar->rng.rng); - if (err) { - dev_err(&ar->udev->dev, "Failed to register the random " - "number generator (%d)\n", err); - return err; - } - - ar->rng.initialized = true; - - err = carl9170_rng_get(ar); - if (err) { - carl9170_unregister_hwrng(ar); + if (err) return err; - } - - return 0; -} -#endif /* CONFIG_CARL9170_HWRNG */ - -static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, - struct survey_info *survey) -{ - struct ar9170 *ar = hw->priv; - struct ieee80211_channel *chan; - struct ieee80211_supported_band *band; - int err, b, i; - - chan = ar->channel; - if (!chan) - return -ENODEV; - - if (idx == chan->hw_value) { - mutex_lock(&ar->mutex); - err = carl9170_update_survey(ar, false, true); - mutex_unlock(&ar->mutex); - if (err) - return err; - } - - for (b = 0; b < IEEE80211_NUM_BANDS; b++) { - band = ar->hw->wiphy->bands[b]; - - if (!band) - continue; - - for (i = 0; i < band->n_channels; i++) { - if (band->channels[i].hw_value == idx) { - chan = &band->channels[i]; - goto found; - } - } - } - return -ENOENT; - -found: - memcpy(survey, &ar->survey[idx], sizeof(*survey)); - survey->channel = chan; + survey->channel = ar->channel; survey->filled = SURVEY_INFO_NOISE_DBM; - - if (ar->channel == chan) - survey->filled |= SURVEY_INFO_IN_USE; - - if (ar->fw.hw_counters) { - survey->filled |= SURVEY_INFO_CHANNEL_TIME | - SURVEY_INFO_CHANNEL_TIME_BUSY | - SURVEY_INFO_CHANNEL_TIME_TX; - } - + survey->noise = ar->noise[0]; return 0; } @@ -1753,7 +1569,6 @@ void *carl9170_alloc(size_t priv_size) INIT_WORK(&ar->ping_work, carl9170_ping_work); INIT_WORK(&ar->restart_work, carl9170_restart_work); INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); - INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work); INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); INIT_LIST_HEAD(&ar->tx_ampdu_list); rcu_assign_pointer(ar->tx_ampdu_iter, @@ -1837,7 +1652,6 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) struct ath_regulatory *regulatory = &ar->common.regulatory; unsigned int rx_streams, tx_streams, tx_params = 0; int bands = 0; - int chans = 0; if (ar->eeprom.length == cpu_to_le16(0xffff)) return -ENODATA; @@ -1861,24 +1675,14 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &carl9170_band_2GHz; - chans += carl9170_band_2GHz.n_channels; bands++; } if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &carl9170_band_5GHz; - chans += carl9170_band_5GHz.n_channels; bands++; } - if (!bands) - return -EINVAL; - - ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL); - if (!ar->survey) - return -ENOMEM; - ar->num_channels = chans; - /* * I measured this, a bandswitch takes roughly * 135 ms and a frequency switch about 80. @@ -1897,7 +1701,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) /* second part of wiphy init */ SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); - return 0; + return bands ? 0 : -EINVAL; } static int carl9170_reg_notifier(struct wiphy *wiphy, @@ -1981,12 +1785,6 @@ int carl9170_register(struct ar9170 *ar) goto err_unreg; #endif /* CONFIG_CARL9170_WPC */ -#ifdef CONFIG_CARL9170_HWRNG - err = carl9170_register_hwrng(ar); - if (err) - goto err_unreg; -#endif /* CONFIG_CARL9170_HWRNG */ - dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n", wiphy_name(ar->hw->wiphy)); @@ -2019,10 +1817,6 @@ void carl9170_unregister(struct ar9170 *ar) } #endif /* CONFIG_CARL9170_WPC */ -#ifdef CONFIG_CARL9170_HWRNG - carl9170_unregister_hwrng(ar); -#endif /* CONFIG_CARL9170_HWRNG */ - carl9170_cancel_worker(ar); cancel_work_sync(&ar->restart_work); @@ -2040,9 +1834,6 @@ void carl9170_free(struct ar9170 *ar) kfree(ar->mem_bitmap); ar->mem_bitmap = NULL; - kfree(ar->survey); - ar->survey = NULL; - mutex_destroy(&ar->mutex); ieee80211_free_hw(ar->hw); diff --git a/trunk/drivers/net/wireless/ath/carl9170/phy.c b/trunk/drivers/net/wireless/ath/carl9170/phy.c index 472efc7e3402..aa147a9120b6 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/phy.c +++ b/trunk/drivers/net/wireless/ath/carl9170/phy.c @@ -578,10 +578,11 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) if (err) return err; - if (!ar->fw.hw_counters) { - err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, - is_2ghz ? 0x5163 : 0x5143); - } + /* XXX: remove magic! */ + if (is_2ghz) + err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163); + else + err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143); return err; } @@ -1573,9 +1574,6 @@ int carl9170_get_noisefloor(struct ar9170 *ar) AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); } - if (ar->channel) - ar->survey[ar->channel->hw_value].noise = ar->noise[0]; - return 0; } @@ -1768,6 +1766,10 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, ar->chan_fail = 0; } + err = carl9170_get_noisefloor(ar); + if (err) + return err; + if (ar->heavy_clip) { err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, 0x200 | ar->heavy_clip); diff --git a/trunk/drivers/net/wireless/ath/carl9170/version.h b/trunk/drivers/net/wireless/ath/carl9170/version.h index e651db856344..64703778cfea 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/version.h +++ b/trunk/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H #define CARL9170FW_VERSION_YEAR 11 -#define CARL9170FW_VERSION_MONTH 8 -#define CARL9170FW_VERSION_DAY 15 +#define CARL9170FW_VERSION_MONTH 6 +#define CARL9170FW_VERSION_DAY 30 #define CARL9170FW_VERSION_GIT "1.9.4" #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/trunk/drivers/net/wireless/ath/main.c b/trunk/drivers/net/wireless/ath/main.c index d9218fe02036..c325202fdc5f 100644 --- a/trunk/drivers/net/wireless/ath/main.c +++ b/trunk/drivers/net/wireless/ath/main.c @@ -57,18 +57,22 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, } EXPORT_SYMBOL(ath_rxbuf_alloc); -void ath_printk(const char *level, const char *fmt, ...) +int ath_printk(const char *level, struct ath_common *common, + const char *fmt, ...) { struct va_format vaf; va_list args; + int rtn; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - printk("%sath: %pV", level, &vaf); + rtn = printk("%sath: %pV", level, &vaf); va_end(args); + + return rtn; } EXPORT_SYMBOL(ath_printk); diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index b97a40ed5fff..b81a2a1c2618 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -124,12 +124,12 @@ config B43_PHY_LP (802.11a support is optional, and currently disabled). config B43_PHY_HT - bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)" - depends on B43 && EXPERIMENTAL + bool "Support for HT-PHY devices (BROKEN)" + depends on B43 && BROKEN ---help--- Support for the HT-PHY. - Enables support for BCM4331 and possibly other chipsets with that PHY. + Say N, this is BROKEN and crashes driver. config B43_PHY_LCN bool "Support for LCN-PHY devices (BROKEN)" @@ -169,3 +169,13 @@ config B43_DEBUG Say N, if you are a distributor or user building a release kernel for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. + +config B43_FORCE_PIO + bool "Force usage of PIO instead of DMA" + depends on B43 && B43_DEBUG + ---help--- + This will disable DMA and always enable PIO instead. + + Say N! + This is only for debugging the PIO engine code. You do + _NOT_ want to enable this. diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index f8615cdf1075..c818b0bc88ec 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -17,6 +17,11 @@ #include "phy_common.h" +/* The unique identifier of the firmware that's officially supported by + * this driver version. */ +#define B43_SUPPORTED_FIRMWARE_ID "FW13" + + #ifdef CONFIG_B43_DEBUG # define B43_DEBUG 1 #else @@ -110,8 +115,6 @@ #define B43_MMIO_TSF_CFP_START_LOW 0x604 #define B43_MMIO_TSF_CFP_START_HIGH 0x606 #define B43_MMIO_TSF_CFP_PRETBTT 0x612 -#define B43_MMIO_TSF_CLK_FRAC_LOW 0x62E -#define B43_MMIO_TSF_CLK_FRAC_HIGH 0x630 #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ @@ -591,7 +594,6 @@ struct b43_dma { struct b43_dmaring *rx_ring; u32 translation; /* Routing bits */ - bool translation_in_low; /* Should translation bit go into low addr? */ bool parity; /* Check for parity */ }; @@ -692,12 +694,6 @@ struct b43_firmware_file { enum b43_firmware_file_type type; }; -enum b43_firmware_hdr_format { - B43_FW_HDR_598, - B43_FW_HDR_410, - B43_FW_HDR_351, -}; - /* Pointers to the firmware data and meta information about it. */ struct b43_firmware { /* Microcode */ @@ -714,9 +710,6 @@ struct b43_firmware { /* Firmware patchlevel */ u16 patch; - /* Format of header used by firmware */ - enum b43_firmware_hdr_format hdr_format; - /* Set to true, if we are using an opensource firmware. * Use this to check for proprietary vs opensource. */ bool opensource; @@ -882,7 +875,7 @@ struct b43_wl { struct b43_leds leds; /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ - u8 pio_scratchspace[118] __attribute__((__aligned__(8))); + u8 pio_scratchspace[110] __attribute__((__aligned__(8))); u8 pio_tailspace[4] __attribute__((__aligned__(8))); }; @@ -972,6 +965,12 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev) return dev->__using_pio_transfers; } +#ifdef CONFIG_B43_FORCE_PIO +# define B43_PIO_DEFAULT 1 +#else +# define B43_PIO_DEFAULT 0 +#endif + /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/trunk/drivers/net/wireless/b43/bus.c b/trunk/drivers/net/wireless/b43/bus.c index 424692df239d..05f6c7bff6ab 100644 --- a/trunk/drivers/net/wireless/b43/bus.c +++ b/trunk/drivers/net/wireless/b43/bus.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver Bus abstraction layer - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c index 975d96040548..83cba22ac6e8 100644 --- a/trunk/drivers/net/wireless/b43/dma.c +++ b/trunk/drivers/net/wireless/b43/dma.c @@ -47,38 +47,6 @@ * into separate slots. */ #define TX_SLOTS_PER_FRAME 2 -static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr, - enum b43_addrtype addrtype) -{ - u32 uninitialized_var(addr); - - switch (addrtype) { - case B43_DMA_ADDR_LOW: - addr = lower_32_bits(dmaaddr); - if (dma->translation_in_low) { - addr &= ~SSB_DMA_TRANSLATION_MASK; - addr |= dma->translation; - } - break; - case B43_DMA_ADDR_HIGH: - addr = upper_32_bits(dmaaddr); - if (!dma->translation_in_low) { - addr &= ~SSB_DMA_TRANSLATION_MASK; - addr |= dma->translation; - } - break; - case B43_DMA_ADDR_EXT: - if (dma->translation_in_low) - addr = lower_32_bits(dmaaddr); - else - addr = upper_32_bits(dmaaddr); - addr &= SSB_DMA_TRANSLATION_MASK; - addr >>= SSB_DMA_TRANSLATION_SHIFT; - break; - } - - return addr; -} /* 32bit DMA ops. */ static @@ -109,9 +77,10 @@ static void op32_fill_descriptor(struct b43_dmaring *ring, slot = (int)(&(desc->dma32) - descbase); B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); - addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); - + addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); + addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; + addr |= ring->dev->dma.translation; ctl = bufsize & B43_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -201,10 +170,11 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, slot = (int)(&(desc->dma64) - descbase); B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); - addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH); - addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); - + addrlo = (u32) (dmaaddr & 0xFFFFFFFF); + addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); + addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; + addrhi |= ring->dev->dma.translation; if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -419,34 +389,33 @@ static int alloc_ringmemory(struct b43_dmaring *ring) gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K - * alignment and 8K buffers for 64-bit DMA with 8K alignment. - * In practice we could use smaller buffers for the latter, but the - * alignment is really important because of the hardware bug. If bit - * 0x00001000 is used in DMA address, some hardware (like BCM4331) - * copies that bit into B43_DMA64_RXSTATUS and we get false values from - * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use - * more than 256 slots for ring. + * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing + * has shown that 4K is sufficient for the latter as long as the buffer + * does not cross an 8K boundary. + * + * For unknown reasons - possibly a hardware error - the BCM4311 rev + * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, + * which accounts for the GFP_DMA flag below. + * + * The flags here must match the flags in free_ringmemory below! */ - u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? - B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; - + if (ring->type == B43_DMA_64BIT) + flags |= GFP_DMA; ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, - ring_mem_size, &(ring->dmabase), - flags); + B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; } - memset(ring->descbase, 0, ring_mem_size); + memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); return 0; } static void free_ringmemory(struct b43_dmaring *ring) { - u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? - B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; - dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size, + dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } @@ -689,37 +658,41 @@ static int dmacontroller_setup(struct b43_dmaring *ring) int err = 0; u32 value; u32 addrext; + u32 trans = ring->dev->dma.translation; bool parity = ring->dev->dma.parity; - u32 addrlo; - u32 addrhi; if (ring->tx) { if (ring->type == B43_DMA_64BIT) { u64 ringbase = (u64) (ring->dmabase); - addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); - addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); - addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); + addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; value = B43_DMA64_TXENABLE; value |= (addrext << B43_DMA64_TXADDREXT_SHIFT) & B43_DMA64_TXADDREXT_MASK; if (!parity) value |= B43_DMA64_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_TXCTL, value); - b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo); - b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi); + b43_dma_write(ring, B43_DMA64_TXRINGLO, + (ringbase & 0xFFFFFFFF)); + b43_dma_write(ring, B43_DMA64_TXRINGHI, + ((ringbase >> 32) & + ~SSB_DMA_TRANSLATION_MASK) + | trans); } else { u32 ringbase = (u32) (ring->dmabase); - addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); - addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); + addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; value = B43_DMA32_TXENABLE; value |= (addrext << B43_DMA32_TXADDREXT_SHIFT) & B43_DMA32_TXADDREXT_MASK; if (!parity) value |= B43_DMA32_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_TXCTL, value); - b43_dma_write(ring, B43_DMA32_TXRING, addrlo); + b43_dma_write(ring, B43_DMA32_TXRING, + (ringbase & ~SSB_DMA_TRANSLATION_MASK) + | trans); } } else { err = alloc_initial_descbuffers(ring); @@ -727,10 +700,9 @@ static int dmacontroller_setup(struct b43_dmaring *ring) goto out; if (ring->type == B43_DMA_64BIT) { u64 ringbase = (u64) (ring->dmabase); - addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); - addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); - addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); + addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT); value |= B43_DMA64_RXENABLE; value |= (addrext << B43_DMA64_RXADDREXT_SHIFT) @@ -738,15 +710,19 @@ static int dmacontroller_setup(struct b43_dmaring *ring) if (!parity) value |= B43_DMA64_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_RXCTL, value); - b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo); - b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi); + b43_dma_write(ring, B43_DMA64_RXRINGLO, + (ringbase & 0xFFFFFFFF)); + b43_dma_write(ring, B43_DMA64_RXRINGHI, + ((ringbase >> 32) & + ~SSB_DMA_TRANSLATION_MASK) + | trans); b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots * sizeof(struct b43_dmadesc64)); } else { u32 ringbase = (u32) (ring->dmabase); - addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); - addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); + addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) + >> SSB_DMA_TRANSLATION_SHIFT; value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT); value |= B43_DMA32_RXENABLE; value |= (addrext << B43_DMA32_RXADDREXT_SHIFT) @@ -754,7 +730,9 @@ static int dmacontroller_setup(struct b43_dmaring *ring) if (!parity) value |= B43_DMA32_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_RXCTL, value); - b43_dma_write(ring, B43_DMA32_RXRING, addrlo); + b43_dma_write(ring, B43_DMA32_RXRING, + (ringbase & ~SSB_DMA_TRANSLATION_MASK) + | trans); b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots * sizeof(struct b43_dmadesc32)); } @@ -880,17 +858,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, ring->current_slot = -1; } else { if (ring->index == 0) { - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE; - ring->frameoffset = B43_DMA0_RX_FW598_FO; - break; - case B43_FW_HDR_410: - case B43_FW_HDR_351: - ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE; - ring->frameoffset = B43_DMA0_RX_FW351_FO; - break; - } + ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; + ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; } else B43_WARN_ON(1); } @@ -1083,25 +1052,6 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) return 0; } -/* Some hardware with 64-bit DMA seems to be bugged and looks for translation - * bit in low address word instead of high one. - */ -static bool b43_dma_translation_in_low_word(struct b43_wldev *dev, - enum b43_dmatype type) -{ - if (type != B43_DMA_64BIT) - return 1; - -#ifdef CONFIG_B43_SSB - if (dev->dev->bus_type == B43_BUS_SSB && - dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && - !(dev->dev->sdev->bus->host_pci->is_pcie && - ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) - return 1; -#endif - return 0; -} - int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; @@ -1127,7 +1077,6 @@ int b43_dma_init(struct b43_wldev *dev) break; #endif } - dma->translation_in_low = b43_dma_translation_in_low_word(dev, type); dma->parity = true; #ifdef CONFIG_B43_BCMA diff --git a/trunk/drivers/net/wireless/b43/dma.h b/trunk/drivers/net/wireless/b43/dma.h index 315b96ed1d90..cdf87094efe8 100644 --- a/trunk/drivers/net/wireless/b43/dma.h +++ b/trunk/drivers/net/wireless/b43/dma.h @@ -161,17 +161,13 @@ struct b43_dmadesc_generic { } __packed; /* Misc DMA constants */ -#define B43_DMA32_RINGMEMSIZE 4096 -#define B43_DMA64_RINGMEMSIZE 8192 -/* Offset of frame with actual data */ -#define B43_DMA0_RX_FW598_FO 38 -#define B43_DMA0_RX_FW351_FO 30 +#define B43_DMA_RINGMEMSIZE PAGE_SIZE +#define B43_DMA0_RX_FRAMEOFFSET 30 /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 #define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) -#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) /* Pointer poison */ #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) @@ -216,12 +212,6 @@ enum b43_dmatype { B43_DMA_64BIT = 64, }; -enum b43_addrtype { - B43_DMA_ADDR_LOW, - B43_DMA_ADDR_HIGH, - B43_DMA_ADDR_EXT, -}; - struct b43_dmaring { /* Lowlevel DMA ops. */ const struct b43_dma_ops *ops; diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 24077023d484..d2661aaff50f 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -7,7 +7,6 @@ Copyright (c) 2005-2009 Michael Buesch Copyright (c) 2005 Danny van Dyk Copyright (c) 2005 Andreas Jaggi - Copyright (c) 2010-2011 Rafał Miłecki SDIO support Copyright (c) 2009 Albert Herranz @@ -65,9 +64,9 @@ MODULE_AUTHOR("Martin Langer"); MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_AUTHOR("Gábor Stefanik"); -MODULE_AUTHOR("Rafał Miłecki"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); MODULE_FIRMWARE("b43/ucode11.fw"); MODULE_FIRMWARE("b43/ucode13.fw"); MODULE_FIRMWARE("b43/ucode14.fw"); @@ -109,7 +108,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -static int b43_modparam_pio = 0; +static int b43_modparam_pio = B43_PIO_DEFAULT; module_param_named(pio, b43_modparam_pio, int, 0644); MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); @@ -321,10 +320,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev); static int b43_wireless_core_init(struct b43_wldev *dev); static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); static int b43_wireless_core_start(struct b43_wldev *dev); -static void b43_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, - u32 changed); static int b43_ratelimit(struct b43_wl *wl) { @@ -2515,12 +2510,6 @@ static int b43_upload_microcode(struct b43_wldev *dev) } dev->fw.rev = fwrev; dev->fw.patch = fwpatch; - if (dev->fw.rev >= 598) - dev->fw.hdr_format = B43_FW_HDR_598; - else if (dev->fw.rev >= 410) - dev->fw.hdr_format = B43_FW_HDR_410; - else - dev->fw.hdr_format = B43_FW_HDR_351; dev->fw.opensource = (fwdate == 0xFFFF); /* Default to use-all-queues. */ @@ -2568,7 +2557,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) dev->fw.rev, dev->fw.patch); wiphy->hw_version = dev->dev->core_id; - if (dev->fw.hdr_format == B43_FW_HDR_351) { + if (b43_is_old_txhdr_format(dev)) { /* We're over the deadline, but we keep support for old fw * until it turns out to be in major conflict with something new. */ b43warn(dev->wl, "You are using an old firmware image. " @@ -2954,8 +2943,6 @@ static void b43_rate_memory_init(struct b43_wldev *dev) case B43_PHYTYPE_G: case B43_PHYTYPE_N: case B43_PHYTYPE_LP: - case B43_PHYTYPE_HT: - case B43_PHYTYPE_LCN: b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); @@ -3791,24 +3778,14 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; int antenna; int err = 0; - bool reload_bss = false; mutex_lock(&wl->mutex); - dev = wl->current_dev; - /* Switch the band (if necessary). This might change the active core. */ err = b43_switch_band(wl, conf->channel); if (err) goto out_unlock_mutex; - - /* Need to reload all settings if the core changed */ - if (dev != wl->current_dev) { - dev = wl->current_dev; - changed = ~0; - reload_bss = true; - } - + dev = wl->current_dev; phy = &dev->phy; if (conf_is_ht(conf)) @@ -3869,9 +3846,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) out_unlock_mutex: mutex_unlock(&wl->mutex); - if (wl->vif && reload_bss) - b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0); - return err; } @@ -3960,8 +3934,7 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BEACON_INT && (b43_is_mode(wl, NL80211_IFTYPE_AP) || b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || - b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) && - conf->beacon_int) + b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) b43_set_beacon_int(dev, conf->beacon_int); if (changed & BSS_CHANGED_BASIC_RATES) @@ -4134,13 +4107,10 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw, * because the core might be gone away while we unlocked the mutex. */ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) { - struct b43_wl *wl; + struct b43_wl *wl = dev->wl; struct b43_wldev *orig_dev; u32 mask; - if (!dev) - return NULL; - wl = dev->wl; redo: if (!dev || b43_status(dev) < B43_STAT_STARTED) return dev; @@ -4659,13 +4629,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); if (b43_bus_host_is_pcmcia(dev->dev) || - b43_bus_host_is_sdio(dev->dev)) { - dev->__using_pio_transfers = 1; - err = b43_pio_init(dev); - } else if (dev->use_pio) { - b43warn(dev->wl, "Forced PIO by use_pio module parameter. " - "This should not be needed and will result in lower " - "performance.\n"); + b43_bus_host_is_sdio(dev->dev) || + dev->use_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { @@ -4737,9 +4702,6 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, out_mutex_unlock: mutex_unlock(&wl->mutex); - if (err == 0) - b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0); - return err; } @@ -4810,9 +4772,6 @@ static int b43_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); - /* reload configuration */ - b43_op_config(hw, ~0); - return err; } @@ -4969,18 +4928,10 @@ static void b43_chip_reset(struct work_struct *work) if (err) wl->current_dev = NULL; /* Failed to init the dev. */ mutex_unlock(&wl->mutex); - - if (err) { + if (err) b43err(wl, "Controller restart FAILED\n"); - return; - } - - /* reload configuration */ - b43_op_config(wl->hw, ~0); - if (wl->vif) - b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0); - - b43info(wl, "Controller restarted\n"); + else + b43info(wl, "Controller restarted\n"); } static int b43_setup_bands(struct b43_wldev *dev, @@ -5465,7 +5416,8 @@ static void b43_print_driverinfo(void) feat_sdio = "S"; #endif printk(KERN_INFO "Broadcom 43xx driver loaded " - "[ Features: %s%s%s%s%s ]\n", + "[ Features: %s%s%s%s%s, Firmware-ID: " + B43_SUPPORTED_FIRMWARE_ID " ]\n", feat_pci, feat_pcmcia, feat_nphy, feat_leds, feat_sdio); } diff --git a/trunk/drivers/net/wireless/b43/phy_common.c b/trunk/drivers/net/wireless/b43/phy_common.c index 3ea44bb03684..07f009ff5ee2 100644 --- a/trunk/drivers/net/wireless/b43/phy_common.c +++ b/trunk/drivers/net/wireless/b43/phy_common.c @@ -448,38 +448,6 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type) channel_type == NL80211_CHAN_HT40PLUS); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ -void b43_phy_force_clock(struct b43_wldev *dev, bool force) -{ - u32 tmp; - - WARN_ON(dev->phy.type != B43_PHYTYPE_N && - dev->phy.type != B43_PHYTYPE_HT); - - switch (dev->dev->bus_type) { -#ifdef CONFIG_B43_BCMA - case B43_BUS_BCMA: - tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); - if (force) - tmp |= BCMA_IOCTL_FGC; - else - tmp &= ~BCMA_IOCTL_FGC; - bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); - break; -#endif -#ifdef CONFIG_B43_SSB - case B43_BUS_SSB: - tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); - if (force) - tmp |= SSB_TMSLOW_FGC; - else - tmp &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); - break; -#endif - } -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { diff --git a/trunk/drivers/net/wireless/b43/phy_common.h b/trunk/drivers/net/wireless/b43/phy_common.h index 9233b13fc16d..aa77ba612a92 100644 --- a/trunk/drivers/net/wireless/b43/phy_common.h +++ b/trunk/drivers/net/wireless/b43/phy_common.h @@ -444,8 +444,6 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type); -void b43_phy_force_clock(struct b43_wldev *dev, bool force); - struct b43_c32 b43_cordic(int theta); #endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/trunk/drivers/net/wireless/b43/phy_ht.c b/trunk/drivers/net/wireless/b43/phy_ht.c index 7416c5e9154d..7c40919651a7 100644 --- a/trunk/drivers/net/wireless/b43/phy_ht.c +++ b/trunk/drivers/net/wireless/b43/phy_ht.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n HT-PHY support - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -153,92 +151,6 @@ static void b43_radio_2059_init(struct b43_wldev *dev) b43_radio_mask(dev, 0x11, ~0x0008); } -/************************************************** - * Various PHY ops - **************************************************/ - -static void b43_phy_ht_zero_extg(struct b43_wldev *dev) -{ - u8 i, j; - u16 base[] = { 0x40, 0x60, 0x80 }; - - for (i = 0; i < ARRAY_SIZE(base); i++) { - for (j = 0; j < 4; j++) - b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); - } - - for (i = 0; i < ARRAY_SIZE(base); i++) - b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); -} - -/* Some unknown AFE (Analog Frondned) op */ -static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) -{ - u8 i; - - const u16 ctl_regs[3][2] = { - { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, - { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, - { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, - }; - - for (i = 0; i < 3; i++) { - /* TODO: verify masks&sets */ - b43_phy_set(dev, ctl_regs[i][1], 0x4); - b43_phy_set(dev, ctl_regs[i][0], 0x4); - b43_phy_mask(dev, ctl_regs[i][1], ~0x1); - b43_phy_set(dev, ctl_regs[i][0], 0x1); - b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); - b43_phy_mask(dev, ctl_regs[i][0], ~0x4); - } -} - -static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) -{ - u8 i; - - u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); - b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); - - b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); - for (i = 0; i < 200; i++) { - if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { - i = 0; - break; - } - msleep(1); - } - if (i) - b43err(dev->wl, "Forcing RF sequence timeout\n"); - - b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); -} - -static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) -{ - clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); - clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); - clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); -} - -static void b43_phy_ht_bphy_init(struct b43_wldev *dev) -{ - unsigned int i; - u16 val; - - val = 0x1E1F; - for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); - val -= 0x202; - } - val = 0x3E3F; - for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); - val -= 0x202; - } - b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); -} - /************************************************** * Channel switching ops. **************************************************/ @@ -343,125 +255,8 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) static int b43_phy_ht_op_init(struct b43_wldev *dev) { - u16 tmp; - u16 clip_state[3]; - b43_phy_ht_tables_init(dev); - b43_phy_mask(dev, 0x0be, ~0x2); - b43_phy_set(dev, 0x23f, 0x7ff); - b43_phy_set(dev, 0x240, 0x7ff); - b43_phy_set(dev, 0x241, 0x7ff); - - b43_phy_ht_zero_extg(dev); - - b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); - - b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); - b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); - b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); - - b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); - b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); - b43_phy_write(dev, 0x20d, 0xb8); - b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); - b43_phy_write(dev, 0x70, 0x50); - b43_phy_write(dev, 0x1ff, 0x30); - - if (0) /* TODO: condition */ - ; /* TODO: PHY op on reg 0x217 */ - - b43_phy_read(dev, 0xb0); /* TODO: what for? */ - b43_phy_set(dev, 0xb0, 0x1); - - b43_phy_set(dev, 0xb1, 0x91); - b43_phy_write(dev, 0x32f, 0x0003); - b43_phy_write(dev, 0x077, 0x0010); - b43_phy_write(dev, 0x0b4, 0x0258); - b43_phy_mask(dev, 0x17e, ~0x4000); - - b43_phy_write(dev, 0x0b9, 0x0072); - - b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); - b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); - b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); - - b43_phy_ht_afe_unk1(dev); - - b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, - 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); - - b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); - b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); - - b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); - b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); - b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); - - b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, - 0x8e, 0x96, 0x96, 0x96); - b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, - 0x8f, 0x9f, 0x9f, 0x9f); - b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, - 0x8f, 0x9f, 0x9f, 0x9f); - - b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); - b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); - b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); - - b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); - b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); - b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); - b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); - - b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, - 0x09, 0x0e, 0x13, 0x18); - b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, - 0x09, 0x0e, 0x13, 0x18); - /* TODO: Did wl mean 2 instead of 40? */ - b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, - 0x09, 0x0e, 0x13, 0x18); - - b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); - b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); - b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); - - b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); - b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); - b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); - b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); - - /* Copy some tables entries */ - tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); - b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); - tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); - b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); - tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); - b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); - - /* Reset CCA */ - b43_phy_force_clock(dev, true); - tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); - b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); - b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); - b43_phy_force_clock(dev, false); - - b43_mac_phy_clock_set(dev, true); - - b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); - b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); - - /* TODO: PHY op on reg 0xb0 */ - - /* TODO: Should we restore it? Or store it in global PHY info? */ - b43_phy_ht_read_clip_detection(dev, clip_state); - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - b43_phy_ht_bphy_init(dev); - - b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), - B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); - return 0; } diff --git a/trunk/drivers/net/wireless/b43/phy_ht.h b/trunk/drivers/net/wireless/b43/phy_ht.h index 6544c4293b34..7ad7affc8df0 100644 --- a/trunk/drivers/net/wireless/b43/phy_ht.h +++ b/trunk/drivers/net/wireless/b43/phy_ht.h @@ -4,11 +4,7 @@ #include "phy_common.h" -#define B43_PHY_HT_BBCFG 0x001 /* BB config */ -#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */ -#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */ #define B43_PHY_HT_BANDCTL 0x009 /* Band control */ -#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */ #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ @@ -19,21 +15,6 @@ #define B43_PHY_HT_BW5 0x1D2 #define B43_PHY_HT_BW6 0x1D3 -#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) -#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) -#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) - -#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) -#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) -#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ -#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ -#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */ -#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */ -#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */ -#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */ -#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004) -/* Values for the status are the same as for the trigger */ - #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) #define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110) diff --git a/trunk/drivers/net/wireless/b43/phy_lcn.c b/trunk/drivers/net/wireless/b43/phy_lcn.c index d1dfeec7bc28..9f7dbbd5ced6 100644 --- a/trunk/drivers/net/wireless/b43/phy_lcn.c +++ b/trunk/drivers/net/wireless/b43/phy_lcn.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n LCN-PHY support - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -29,450 +27,12 @@ #include "tables_phy_lcn.h" #include "main.h" -/************************************************** - * Radio 2064. - **************************************************/ - -/* wlc_lcnphy_radio_2064_channel_tune_4313 */ -static void b43_radio_2064_channel_setup(struct b43_wldev *dev) -{ - u16 save[2]; - - b43_radio_set(dev, 0x09d, 0x4); - b43_radio_write(dev, 0x09e, 0xf); - - /* Channel specific values in theory, in practice always the same */ - b43_radio_write(dev, 0x02a, 0xb); - b43_radio_maskset(dev, 0x030, ~0x3, 0xa); - b43_radio_maskset(dev, 0x091, ~0x3, 0); - b43_radio_maskset(dev, 0x038, ~0xf, 0x7); - b43_radio_maskset(dev, 0x030, ~0xc, 0x8); - b43_radio_maskset(dev, 0x05e, ~0xf, 0x8); - b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80); - b43_radio_write(dev, 0x06c, 0x80); - - save[0] = b43_radio_read(dev, 0x044); - save[1] = b43_radio_read(dev, 0x12b); - - b43_radio_set(dev, 0x044, 0x7); - b43_radio_set(dev, 0x12b, 0xe); - - /* TODO */ - - b43_radio_write(dev, 0x040, 0xfb); - - b43_radio_write(dev, 0x041, 0x9a); - b43_radio_write(dev, 0x042, 0xa3); - b43_radio_write(dev, 0x043, 0x0c); - - /* TODO */ - - b43_radio_set(dev, 0x044, 0x0c); - udelay(1); - - b43_radio_write(dev, 0x044, save[0]); - b43_radio_write(dev, 0x12b, save[1]); - - if (dev->phy.rev == 1) { - /* brcmsmac uses outdated 0x3 for 0x038 */ - b43_radio_write(dev, 0x038, 0x0); - b43_radio_write(dev, 0x091, 0x7); - } -} - -/* wlc_radio_2064_init */ -static void b43_radio_2064_init(struct b43_wldev *dev) -{ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_radio_write(dev, 0x09c, 0x0020); - b43_radio_write(dev, 0x105, 0x0008); - } else { - /* TODO */ - } - b43_radio_write(dev, 0x032, 0x0062); - b43_radio_write(dev, 0x033, 0x0019); - b43_radio_write(dev, 0x090, 0x0010); - b43_radio_write(dev, 0x010, 0x0000); - if (dev->phy.rev == 1) { - b43_radio_write(dev, 0x060, 0x007f); - b43_radio_write(dev, 0x061, 0x0072); - b43_radio_write(dev, 0x062, 0x007f); - } - b43_radio_write(dev, 0x01d, 0x0002); - b43_radio_write(dev, 0x01e, 0x0006); - - b43_phy_write(dev, 0x4ea, 0x4688); - b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2); - b43_phy_mask(dev, 0x4eb, ~0x01c0); - b43_phy_maskset(dev, 0x46a, 0xff00, 0x19); - - b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0); - - b43_radio_mask(dev, 0x05b, (u16) ~0xff02); - b43_radio_set(dev, 0x004, 0x40); - b43_radio_set(dev, 0x120, 0x10); - b43_radio_set(dev, 0x078, 0x80); - b43_radio_set(dev, 0x129, 0x2); - b43_radio_set(dev, 0x057, 0x1); - b43_radio_set(dev, 0x05b, 0x2); - - /* TODO: wait for some bit to be set */ - b43_radio_read(dev, 0x05c); - - b43_radio_mask(dev, 0x05b, (u16) ~0xff02); - b43_radio_mask(dev, 0x057, (u16) ~0xff01); - - b43_phy_write(dev, 0x933, 0x2d6b); - b43_phy_write(dev, 0x934, 0x2d6b); - b43_phy_write(dev, 0x935, 0x2d6b); - b43_phy_write(dev, 0x936, 0x2d6b); - b43_phy_write(dev, 0x937, 0x016b); - - b43_radio_mask(dev, 0x057, (u16) ~0xff02); - b43_radio_write(dev, 0x0c2, 0x006f); -} - -/************************************************** - * Various PHY ops - **************************************************/ - -/* wlc_lcnphy_toggle_afe_pwdn */ -static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev) -{ - u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2); - u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1); - - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1); - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1); - - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1); - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1); - - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2); - b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); -} - -/* wlc_lcnphy_clear_tx_power_offsets */ -static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev) -{ - u8 i; - - if (1) { /* FIXME */ - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340); - for (i = 0; i < 30; i++) { - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); - } - } - - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80); - for (i = 0; i < 64; i++) { - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); - } -} - -/* wlc_lcnphy_rev0_baseband_init */ -static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev) -{ - b43_radio_write(dev, 0x11c, 0); - - b43_phy_write(dev, 0x43b, 0); - b43_phy_write(dev, 0x43c, 0); - b43_phy_write(dev, 0x44c, 0); - b43_phy_write(dev, 0x4e6, 0); - b43_phy_write(dev, 0x4f9, 0); - b43_phy_write(dev, 0x4b0, 0); - b43_phy_write(dev, 0x938, 0); - b43_phy_write(dev, 0x4b0, 0); - b43_phy_write(dev, 0x44e, 0); - - b43_phy_set(dev, 0x567, 0x03); - - b43_phy_set(dev, 0x44a, 0x44); - b43_phy_write(dev, 0x44a, 0x80); - - if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)) - ; /* TODO */ - b43_phy_maskset(dev, 0x634, ~0xff, 0xc); - if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) { - b43_phy_maskset(dev, 0x634, ~0xff, 0xa); - b43_phy_write(dev, 0x910, 0x1); - } - - b43_phy_write(dev, 0x910, 0x1); - - b43_phy_maskset(dev, 0x448, ~0x300, 0x100); - b43_phy_maskset(dev, 0x608, ~0xff, 0x17); - b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea); -} - -/* wlc_lcnphy_bu_tweaks */ -static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev) -{ - b43_phy_set(dev, 0x805, 0x1); - - b43_phy_maskset(dev, 0x42f, ~0x7, 0x3); - b43_phy_maskset(dev, 0x030, ~0x7, 0x3); - - b43_phy_write(dev, 0x414, 0x1e10); - b43_phy_write(dev, 0x415, 0x0640); - - b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700); - - b43_phy_set(dev, 0x44a, 0x44); - b43_phy_write(dev, 0x44a, 0x80); - - b43_phy_maskset(dev, 0x434, ~0xff, 0xfd); - b43_phy_maskset(dev, 0x420, ~0xff, 0x10); - - if (dev->dev->bus_sprom->board_rev >= 0x1204) - b43_radio_set(dev, 0x09b, 0xf0); - - b43_phy_write(dev, 0x7d6, 0x0902); - - /* TODO: more ops */ - - if (dev->phy.rev == 1) { - /* TODO: more ops */ - - b43_phy_lcn_clear_tx_power_offsets(dev); - } -} - -/* wlc_lcnphy_vbat_temp_sense_setup */ -static void b43_phy_lcn_sense_setup(struct b43_wldev *dev) -{ - u8 i; - - u16 save_radio_regs[6][2] = { - { 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 }, - { 0x025, 0 }, { 0x112, 0 }, - }; - u16 save_phy_regs[14][2] = { - { 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 }, - { 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 }, - { 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 }, - { 0x40d, 0 }, { 0x4a2, 0 }, - }; - u16 save_radio_4a4; - - for (i = 0; i < 6; i++) - save_radio_regs[i][1] = b43_radio_read(dev, - save_radio_regs[i][0]); - for (i = 0; i < 14; i++) - save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]); - save_radio_4a4 = b43_radio_read(dev, 0x4a4); - - /* TODO: config sth */ - - for (i = 0; i < 6; i++) - b43_radio_write(dev, save_radio_regs[i][0], - save_radio_regs[i][1]); - for (i = 0; i < 14; i++) - b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]); - b43_radio_write(dev, 0x4a4, save_radio_4a4); -} - -/************************************************** - * Channel switching ops. - **************************************************/ - -static int b43_phy_lcn_set_channel(struct b43_wldev *dev, - struct ieee80211_channel *channel, - enum nl80211_channel_type channel_type) -{ - /* TODO: PLL and PHY ops */ - - b43_phy_set(dev, 0x44a, 0x44); - b43_phy_write(dev, 0x44a, 0x80); - - b43_phy_set(dev, 0x44a, 0x44); - b43_phy_write(dev, 0x44a, 0x80); - - b43_radio_2064_channel_setup(dev); - mdelay(1); - - b43_phy_lcn_afe_set_unset(dev); - - /* TODO */ - - return 0; -} - -/************************************************** - * Basic PHY ops. - **************************************************/ - -static int b43_phy_lcn_op_allocate(struct b43_wldev *dev) -{ - struct b43_phy_lcn *phy_lcn; - - phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL); - if (!phy_lcn) - return -ENOMEM; - dev->phy.lcn = phy_lcn; - - return 0; -} - -static void b43_phy_lcn_op_free(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_lcn *phy_lcn = phy->lcn; - - kfree(phy_lcn); - phy->lcn = NULL; -} - -static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_lcn *phy_lcn = phy->lcn; - - memset(phy_lcn, 0, sizeof(*phy_lcn)); -} - -/* wlc_phy_init_lcnphy */ -static int b43_phy_lcn_op_init(struct b43_wldev *dev) -{ - b43_phy_set(dev, 0x44a, 0x80); - b43_phy_mask(dev, 0x44a, 0x7f); - b43_phy_set(dev, 0x6d1, 0x80); - b43_phy_write(dev, 0x6d0, 0x7); - - b43_phy_lcn_afe_set_unset(dev); - - b43_phy_write(dev, 0x60a, 0xa0); - b43_phy_write(dev, 0x46a, 0x19); - b43_phy_maskset(dev, 0x663, 0xFF00, 0x64); - - b43_phy_lcn_tables_init(dev); - - b43_phy_lcn_rev0_baseband_init(dev); - b43_phy_lcn_bu_tweaks(dev); - - if (dev->phy.radio_ver == 0x2064) - b43_radio_2064_init(dev); - else - B43_WARN_ON(1); - - b43_phy_lcn_sense_setup(dev); - - return 0; -} - -static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, - bool blocked) -{ - if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) - b43err(dev->wl, "MAC not suspended\n"); - - if (blocked) { - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00); - b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00); - - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00); - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2); - b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808); - - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8); - b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8); - } else { - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00); - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808); - b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8); - } -} - -static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on) -{ - if (on) { - b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7); - } else { - b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7); - b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7); - } -} - -static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel) -{ - struct ieee80211_channel *channel = dev->wl->hw->conf.channel; - enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type; - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if ((new_channel < 1) || (new_channel > 14)) - return -EINVAL; - } else { - return -EINVAL; - } - - return b43_phy_lcn_set_channel(dev, channel, channel_type); -} - -static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) -{ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - return 1; - return 36; -} - -static enum b43_txpwr_result -b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) -{ - return B43_TXPWR_RES_DONE; -} - -static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev) -{ -} - -/************************************************** - * R/W ops. - **************************************************/ - -static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - return b43_read16(dev, B43_MMIO_PHY_DATA); -} - -static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, value); -} - -static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, - u16 set) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, - (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); -} - -static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg) -{ - /* LCN-PHY needs 0x200 for read access */ - reg |= 0x200; - - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); - return b43_read16(dev, B43_MMIO_RADIO24_DATA); -} - -static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg, - u16 value) -{ - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); - b43_write16(dev, B43_MMIO_RADIO24_DATA, value); -} - /************************************************** * PHY ops struct. **************************************************/ const struct b43_phy_operations b43_phyops_lcn = { + /* .allocate = b43_phy_lcn_op_allocate, .free = b43_phy_lcn_op_free, .prepare_structs = b43_phy_lcn_op_prepare_structs, @@ -488,4 +48,5 @@ const struct b43_phy_operations b43_phyops_lcn = { .get_default_chan = b43_phy_lcn_op_get_default_chan, .recalc_txpower = b43_phy_lcn_op_recalc_txpower, .adjust_txpower = b43_phy_lcn_op_adjust_txpower, + */ }; diff --git a/trunk/drivers/net/wireless/b43/phy_lcn.h b/trunk/drivers/net/wireless/b43/phy_lcn.h index 25f06e8d4531..c046c2a6cab4 100644 --- a/trunk/drivers/net/wireless/b43/phy_lcn.h +++ b/trunk/drivers/net/wireless/b43/phy_lcn.h @@ -4,20 +4,6 @@ #include "phy_common.h" -#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B) -#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C) -#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C) -#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D) -#define B43_PHY_LCN_TABLE_ADDR B43_PHY_OFDM(0x055) /* Table address */ -#define B43_PHY_LCN_TABLE_DATALO B43_PHY_OFDM(0x056) /* Table data low */ -#define B43_PHY_LCN_TABLE_DATAHI B43_PHY_OFDM(0x057) /* Table data high */ -#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0) -#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1) -#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7) -#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9) -#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA) - - struct b43_phy_lcn { }; @@ -25,4 +11,4 @@ struct b43_phy_lcn { struct b43_phy_operations; extern const struct b43_phy_operations b43_phyops_lcn; -#endif /* B43_PHY_LCN_H_ */ +#endif /* B43_PHY_LCN_H_ */ \ No newline at end of file diff --git a/trunk/drivers/net/wireless/b43/phy_n.c b/trunk/drivers/net/wireless/b43/phy_n.c index b17d9b6c33a5..3b46360da99b 100644 --- a/trunk/drivers/net/wireless/b43/phy_n.c +++ b/trunk/drivers/net/wireless/b43/phy_n.c @@ -4,7 +4,6 @@ IEEE 802.11n PHY support Copyright (c) 2008 Michael Buesch - Copyright (c) 2010-2011 Rafał Miłecki This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,7 +77,6 @@ enum b43_nphy_rssi_type { B43_NPHY_RSSI_TBD, }; -/* TODO: reorder functions */ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable); static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, @@ -89,14 +87,6 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, u16 value, u8 core, bool off); static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, u16 value, u8 core); -static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev); - -static inline bool b43_nphy_ipa(struct b43_wldev *dev) -{ - enum ieee80211_band band = b43_current_band(dev->wl); - return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) || - (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)); -} void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO @@ -258,25 +248,15 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) { struct b43_phy_n *nphy = dev->phy.n; u8 i; - u16 bmask, val, tmp; - enum ieee80211_band band = b43_current_band(dev->wl); + u16 tmp; if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 1); nphy->txpwrctrl = enable; if (!enable) { - if (dev->phy.rev >= 3 && - (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) & - (B43_NPHY_TXPCTL_CMD_COEFF | - B43_NPHY_TXPCTL_CMD_HWPCTLEN | - B43_NPHY_TXPCTL_CMD_PCTLEN))) { - /* We disable enabled TX pwr ctl, save it's state */ - nphy->tx_pwr_idx[0] = b43_phy_read(dev, - B43_NPHY_C1_TXPCTL_STAT) & 0x7f; - nphy->tx_pwr_idx[1] = b43_phy_read(dev, - B43_NPHY_C2_TXPCTL_STAT) & 0x7f; - } + if (dev->phy.rev >= 3) + ; /* TODO */ b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); for (i = 0; i < 84; i++) @@ -305,67 +285,10 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); - if (dev->phy.rev < 2 && dev->phy.is_40mhz) - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW); + if (dev->phy.rev < 2 && 0) + ; /* TODO */ } else { - b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, - nphy->adj_pwr_tbl); - b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, - nphy->adj_pwr_tbl); - - bmask = B43_NPHY_TXPCTL_CMD_COEFF | - B43_NPHY_TXPCTL_CMD_HWPCTLEN; - /* wl does useless check for "enable" param here */ - val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; - if (dev->phy.rev >= 3) { - bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN; - if (val) - val |= B43_NPHY_TXPCTL_CMD_PCTLEN; - } - b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); - - if (band == IEEE80211_BAND_5GHZ) { - b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, - ~B43_NPHY_TXPCTL_CMD_INIT, 0x64); - if (dev->phy.rev > 1) - b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, - ~B43_NPHY_TXPCTL_INIT_PIDXI1, - 0x64); - } - - if (dev->phy.rev >= 3) { - if (nphy->tx_pwr_idx[0] != 128 && - nphy->tx_pwr_idx[1] != 128) { - /* Recover TX pwr ctl state */ - b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, - ~B43_NPHY_TXPCTL_CMD_INIT, - nphy->tx_pwr_idx[0]); - if (dev->phy.rev > 1) - b43_phy_maskset(dev, - B43_NPHY_TXPCTL_INIT, - ~0xff, nphy->tx_pwr_idx[1]); - } - } - - if (dev->phy.rev >= 3) { - b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100); - b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100); - } else { - b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000); - } - - if (dev->phy.rev == 2) - b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b); - else if (dev->phy.rev < 2) - b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40); - - if (dev->phy.rev < 2 && dev->phy.is_40mhz) - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW); - - if (b43_nphy_ipa(dev)) { - b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4); - b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4); - } + b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n"); } if (nphy->hang_avoid) @@ -446,23 +369,22 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) else b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); - b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); - tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57)); if (i == 0) tmp = (tmp & 0x00FF) | (bbmult << 8); else tmp = (tmp & 0xFF00) | bbmult; - b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp); - - if (b43_nphy_ipa(dev)) { - u32 tmp32; - u16 reg = (i == 0) ? - B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1; - tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i])); - b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4); - b43_phy_set(dev, reg, 0x4); - } + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp); + + if (0) + ; /* TODO */ } b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); @@ -471,57 +393,6 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } -static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - const u32 *table = NULL; -#if 0 - TODO: b43_ntab_papd_pga_gain_delta_ipa_2* - u32 rfpwr_offset; - u8 pga_gain; - int i; -#endif - - if (phy->rev >= 3) { - if (b43_nphy_ipa(dev)) { - table = b43_nphy_get_ipa_gain_table(dev); - } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { - if (phy->rev == 3) - table = b43_ntab_tx_gain_rev3_5ghz; - if (phy->rev == 4) - table = b43_ntab_tx_gain_rev4_5ghz; - else - table = b43_ntab_tx_gain_rev5plus_5ghz; - } else { - table = b43_ntab_tx_gain_rev3plus_2ghz; - } - } - } else { - table = b43_ntab_tx_gain_rev0_1_2; - } - b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); - b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); - - if (phy->rev >= 3) { -#if 0 - nphy->gmval = (table[0] >> 16) & 0x7000; - - for (i = 0; i < 128; i++) { - pga_gain = (table[i] >> 24) & 0xF; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; - else - rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain]; - b43_ntab_write(dev, B43_NTAB32(26, 576 + i), - rfpwr_offset); - b43_ntab_write(dev, B43_NTAB32(27, 576 + i), - rfpwr_offset); - } -#endif - } -} /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ static void b43_radio_2055_setup(struct b43_wldev *dev, @@ -710,10 +581,14 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) { + struct b43_phy_n *nphy = dev->phy.n; u16 tmp; + enum ieee80211_band band = b43_current_band(dev->wl); + bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ); if (dev->phy.rev >= 3) { - if (b43_nphy_ipa(dev)) { + if (ipa) { tmp = 4; b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); @@ -725,17 +600,49 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ +static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) +{ + u32 tmp; + + if (dev->phy.type != B43_PHYTYPE_N) + return; + + switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + if (force) + tmp |= BCMA_IOCTL_FGC; + else + tmp &= ~BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + break; +#endif +#ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + if (force) + tmp |= SSB_TMSLOW_FGC; + else + tmp &= ~SSB_TMSLOW_FGC; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + break; +#endif + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ static void b43_nphy_reset_cca(struct b43_wldev *dev) { u16 bbcfg; - b43_phy_force_clock(dev, 1); + b43_nphy_bmac_clock_fgc(dev, 1); bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); udelay(1); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); - b43_phy_force_clock(dev, 0); + b43_nphy_bmac_clock_fgc(dev, 0); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); } @@ -1024,7 +931,11 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) { u16 array[4]; - b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array); + int i; + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50); + for (i = 0; i < 4; i++) + array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); @@ -1487,220 +1398,180 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) } } -static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ +static void b43_nphy_workarounds(struct b43_wldev *dev) { - struct b43_phy_n *nphy = dev->phy.n; struct ssb_sprom *sprom = dev->dev->bus_sprom; + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = phy->n; + + u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; + u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; - /* TX to RX */ - u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F }; - u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 }; - /* RX to TX */ - u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, - 0x1F }; - u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F }; - u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; + u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; + u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; u16 tmp16; u32 tmp32; - tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); - tmp32 &= 0xffffff; - b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); - - b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); - b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3); - b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); - b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E); - b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD); - b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); - - b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C); - b43_phy_write(dev, 0x2AE, 0x000C); - - /* TX to RX */ - b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9); - - /* RX to TX */ - if (b43_nphy_ipa(dev)) - b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa, - rx2tx_delays_ipa, 9); - if (nphy->hw_phyrxchain != 3 && - nphy->hw_phyrxchain != nphy->hw_phytxchain) { - if (b43_nphy_ipa(dev)) { - rx2tx_delays[5] = 59; - rx2tx_delays[6] = 1; - rx2tx_events[7] = 0x1F; - } - b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9); - } + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + b43_nphy_classifier(dev, 1, 0); + else + b43_nphy_classifier(dev, 1, 1); - tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? - 0x2 : 0x9C40; - b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16); + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); - b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700); + b43_phy_set(dev, B43_NPHY_IQFLIP, + B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); - b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D); - b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D); + if (dev->phy.rev >= 3) { + tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); + tmp32 &= 0xffffff; + b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); - b43_nphy_gain_ctrl_workarounds(dev); + b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); + b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3); + b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); + b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E); + b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD); + b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); - b43_ntab_write(dev, B43_NTAB32(8, 0), 2); - b43_ntab_write(dev, B43_NTAB32(8, 16), 2); + b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C); + b43_phy_write(dev, 0x2AE, 0x000C); - /* TODO */ + /* TODO */ - b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); - b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); - b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); - b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); - b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); - b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); - b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); - b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); - b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); - b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); - - /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ - - if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || - (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && - b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) - tmp32 = 0x00088888; - else - tmp32 = 0x88888888; - b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32); - b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32); - b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32); - - if (dev->phy.rev == 4 && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { - b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC, - 0x70); - b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC, - 0x70); - } + tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? + 0x2 : 0x9C40; + b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16); - b43_phy_write(dev, 0x224, 0x039C); - b43_phy_write(dev, 0x225, 0x0357); - b43_phy_write(dev, 0x226, 0x0317); - b43_phy_write(dev, 0x227, 0x02D7); - b43_phy_write(dev, 0x228, 0x039C); - b43_phy_write(dev, 0x229, 0x0357); - b43_phy_write(dev, 0x22A, 0x0317); - b43_phy_write(dev, 0x22B, 0x02D7); - b43_phy_write(dev, 0x22C, 0x039C); - b43_phy_write(dev, 0x22D, 0x0357); - b43_phy_write(dev, 0x22E, 0x0317); - b43_phy_write(dev, 0x22F, 0x02D7); -} + b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700); -static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) -{ - struct ssb_sprom *sprom = dev->dev->bus_sprom; - struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = phy->n; + b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D); + b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D); - u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; - u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; + b43_nphy_gain_ctrl_workarounds(dev); - u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; - u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; + b43_ntab_write(dev, B43_NTAB32(8, 0), 2); + b43_ntab_write(dev, B43_NTAB32(8, 16), 2); - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && - nphy->band5g_pwrgain) { - b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); - b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); - } else { - b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); - b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); - } + /* TODO */ - b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A); - b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A); - b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); + b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); + b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); + b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); + b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); + b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); + b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); + b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); + b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); + b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); + b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); + + /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ + + if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR && + b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || + (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && + b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) + tmp32 = 0x00088888; + else + tmp32 = 0x88888888; + b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32); + b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32); + b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32); + + if (dev->phy.rev == 4 && + b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC, + 0x70); + b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC, + 0x70); + } - if (dev->phy.rev < 2) { - b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000); - b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000); - b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800); - b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800); - } + b43_phy_write(dev, 0x224, 0x039C); + b43_phy_write(dev, 0x225, 0x0357); + b43_phy_write(dev, 0x226, 0x0317); + b43_phy_write(dev, 0x227, 0x02D7); + b43_phy_write(dev, 0x228, 0x039C); + b43_phy_write(dev, 0x229, 0x0357); + b43_phy_write(dev, 0x22A, 0x0317); + b43_phy_write(dev, 0x22B, 0x02D7); + b43_phy_write(dev, 0x22C, 0x039C); + b43_phy_write(dev, 0x22D, 0x0357); + b43_phy_write(dev, 0x22E, 0x0317); + b43_phy_write(dev, 0x22F, 0x02D7); + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && + nphy->band5g_pwrgain) { + b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); + b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); + } else { + b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); + b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); + } - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); + b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A); + b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A); + b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); + b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); - if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD && - dev->dev->board_type == 0x8B) { - delays1[0] = 0x1; - delays1[5] = 0x14; - } - b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); - b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); + if (dev->phy.rev < 2) { + b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000); + b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000); + b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); + b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); + b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800); + b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800); + } - b43_nphy_gain_ctrl_workarounds(dev); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); - if (dev->phy.rev < 2) { - if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) - b43_hf_write(dev, b43_hf_read(dev) | - B43_HF_MLADVW); - } else if (dev->phy.rev == 2) { - b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); - b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); - } + if (sprom->boardflags2_lo & 0x100 && + dev->dev->board_type == 0x8B) { + delays1[0] = 0x1; + delays1[5] = 0x14; + } + b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); + b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); - if (dev->phy.rev < 2) - b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, - ~B43_NPHY_SCRAM_SIGCTL_SCM); - - /* Set phase track alpha and beta */ - b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); - b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); - b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); - b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); - b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); - b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); - - b43_phy_mask(dev, B43_NPHY_PIL_DW1, - ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); - - if (dev->phy.rev == 2) - b43_phy_set(dev, B43_NPHY_FINERX2_CGC, - B43_NPHY_FINERX2_CGC_DECGC); -} + b43_nphy_gain_ctrl_workarounds(dev); -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ -static void b43_nphy_workarounds(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = phy->n; + if (dev->phy.rev < 2) { + if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) + b43_hf_write(dev, b43_hf_read(dev) | + B43_HF_MLADVW); + } else if (dev->phy.rev == 2) { + b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); + b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); + } - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) - b43_nphy_classifier(dev, 1, 0); - else - b43_nphy_classifier(dev, 1, 1); + if (dev->phy.rev < 2) + b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, + ~B43_NPHY_SCRAM_SIGCTL_SCM); - if (nphy->hang_avoid) - b43_nphy_stay_in_carrier_search(dev, 1); + /* Set phase track alpha and beta */ + b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); + b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); + b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); + b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); + b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); + b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); - b43_phy_set(dev, B43_NPHY_IQFLIP, - B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); + b43_phy_mask(dev, B43_NPHY_PIL_DW1, + ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); - if (dev->phy.rev >= 3) - b43_nphy_workarounds_rev3plus(dev); - else - b43_nphy_workarounds_rev1_2(dev); + if (dev->phy.rev == 2) + b43_phy_set(dev, B43_NPHY_FINERX2_CGC, + B43_NPHY_FINERX2_CGC_DECGC); + } if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 0); @@ -2296,6 +2167,7 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) { + struct b43_phy_n *nphy = dev->phy.n; u8 i; u16 reg, val; @@ -2359,7 +2231,10 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) enum ieee80211_band band = b43_current_band(dev->wl); - if (b43_nphy_ipa(dev)) + if ((nphy->ipa2g_on && + band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && + band == IEEE80211_BAND_5GHZ)) val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; else val = 0x11; @@ -2734,8 +2609,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { if (dev->phy.rev >= 6) { - if (dev->dev->chip_id == 47162) - return txpwrctrl_tx_gain_ipa_rev5; + /* TODO If the chip is 47162 + return txpwrctrl_tx_gain_ipa_rev5 */ return txpwrctrl_tx_gain_ipa_rev6; } else if (dev->phy.rev >= 5) { return txpwrctrl_tx_gain_ipa_rev5; @@ -2985,7 +2860,10 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) enum ieee80211_band band = b43_current_band(dev->wl); - if (b43_nphy_ipa(dev)) { + if ((nphy->ipa2g_on && + band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && + band == IEEE80211_BAND_5GHZ)) { table = b43_nphy_get_ipa_gain_table(dev); } else { if (band == IEEE80211_BAND_5GHZ) { @@ -3802,7 +3680,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); - if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD || + if (sprom->boardflags2_lo & 0x100 || (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && dev->dev->board_type == 0x8B)) b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); @@ -3821,7 +3699,8 @@ int b43_phy_initn(struct b43_wldev *dev) } tmp2 = b43_current_band(dev->wl); - if (b43_nphy_ipa(dev)) { + if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) { b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, nphy->papd_epsilon_offset[0] << 7); @@ -3836,11 +3715,11 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_workarounds(dev); /* Reset CCA, in init code it differs a little from standard way */ - b43_phy_force_clock(dev, 1); + b43_nphy_bmac_clock_fgc(dev, 1); tmp = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); - b43_phy_force_clock(dev, 0); + b43_nphy_bmac_clock_fgc(dev, 0); b43_mac_phy_clock_set(dev, true); @@ -3859,7 +3738,15 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_tx_power_fix(dev); /* TODO N PHY TX Power Control Idle TSSI */ /* TODO N PHY TX Power Control Setup */ - b43_nphy_tx_gain_table_upload(dev); + + if (phy->rev >= 3) { + /* TODO */ + } else { + b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, + b43_ntab_tx_gain_rev0_1_2); + b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, + b43_ntab_tx_gain_rev0_1_2); + } if (nphy->phyrxchain != 3) b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); @@ -4063,10 +3950,6 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ - /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is - * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ - nphy->tx_pwr_idx[0] = 128; - nphy->tx_pwr_idx[1] = 128; } static void b43_nphy_op_free(struct b43_wldev *dev) diff --git a/trunk/drivers/net/wireless/b43/phy_n.h b/trunk/drivers/net/wireless/b43/phy_n.h index fbf520285bd1..e789a89f1047 100644 --- a/trunk/drivers/net/wireless/b43/phy_n.h +++ b/trunk/drivers/net/wireless/b43/phy_n.h @@ -764,8 +764,6 @@ struct b43_phy_n { u8 cal_orig_pwr_idx[2]; u8 measure_hold; u8 phyrxchain; - u8 hw_phyrxchain; - u8 hw_phytxchain; u8 perical; u32 deaf_count; u32 rxcalparams; @@ -785,8 +783,6 @@ struct b43_phy_n { u16 mphase_txcal_bestcoeffs[11]; bool txpwrctrl; - u8 tx_pwr_idx[2]; - u16 adj_pwr_tbl[84]; u16 txcal_bbmult; u16 txiqlocal_bestc[11]; bool txiqlocal_coeffsvalid; diff --git a/trunk/drivers/net/wireless/b43/pio.c b/trunk/drivers/net/wireless/b43/pio.c index fcff923b3c18..6e4228c3ed1b 100644 --- a/trunk/drivers/net/wireless/b43/pio.c +++ b/trunk/drivers/net/wireless/b43/pio.c @@ -611,7 +611,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) struct b43_wldev *dev = q->dev; struct b43_wl *wl = dev->wl; u16 len; - u32 macstat = 0; + u32 macstat; unsigned int i, padding; struct sk_buff *skb; const char *err_msg = NULL; @@ -676,15 +676,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) goto rx_error; } - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - macstat = le32_to_cpu(rxhdr->format_598.mac_status); - break; - case B43_FW_HDR_410: - case B43_FW_HDR_351: - macstat = le32_to_cpu(rxhdr->format_351.mac_status); - break; - } + macstat = le32_to_cpu(rxhdr->mac_status); if (macstat & B43_RX_MAC_FCSERR) { if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { /* Drop frames with failed FCS. */ diff --git a/trunk/drivers/net/wireless/b43/radio_2055.c b/trunk/drivers/net/wireless/b43/radio_2055.c index 5289a18ddd8c..93643f18c2b3 100644 --- a/trunk/drivers/net/wireless/b43/radio_2055.c +++ b/trunk/drivers/net/wireless/b43/radio_2055.c @@ -4,7 +4,6 @@ IEEE 802.11n PHY and radio device data tables Copyright (c) 2008 Michael Buesch - Copyright (c) 2010 Rafał Miłecki This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/trunk/drivers/net/wireless/b43/radio_2056.c b/trunk/drivers/net/wireless/b43/radio_2056.c index a01f776ca4de..8890df067029 100644 --- a/trunk/drivers/net/wireless/b43/radio_2056.c +++ b/trunk/drivers/net/wireless/b43/radio_2056.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n 2056 radio device data tables - Copyright (c) 2010 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or diff --git a/trunk/drivers/net/wireless/b43/radio_2056.h b/trunk/drivers/net/wireless/b43/radio_2056.h index a7159d8578be..d52df6be705a 100644 --- a/trunk/drivers/net/wireless/b43/radio_2056.h +++ b/trunk/drivers/net/wireless/b43/radio_2056.h @@ -1,3 +1,29 @@ +/* + + Broadcom B43 wireless driver + + Copyright (c) 2010 Rafał Miłecki + + Some parts of the code in this file are derived from the brcm80211 + driver Copyright (c) 2010 Broadcom Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + #ifndef B43_RADIO_2056_H_ #define B43_RADIO_2056_H_ diff --git a/trunk/drivers/net/wireless/b43/radio_2059.c b/trunk/drivers/net/wireless/b43/radio_2059.c index d4ce8a12ff9a..f029f6e1f5d1 100644 --- a/trunk/drivers/net/wireless/b43/radio_2059.c +++ b/trunk/drivers/net/wireless/b43/radio_2059.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n 2059 radio device data tables - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or diff --git a/trunk/drivers/net/wireless/b43/tables_nphy.c b/trunk/drivers/net/wireless/b43/tables_nphy.c index 7b326f2efdc9..916f238a71df 100644 --- a/trunk/drivers/net/wireless/b43/tables_nphy.c +++ b/trunk/drivers/net/wireless/b43/tables_nphy.c @@ -4,7 +4,6 @@ IEEE 802.11n PHY data tables Copyright (c) 2008 Michael Buesch - Copyright (c) 2010 Rafał Miłecki This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/trunk/drivers/net/wireless/b43/tables_phy_ht.c b/trunk/drivers/net/wireless/b43/tables_phy_ht.c index 176c49d74ef4..603938657b15 100644 --- a/trunk/drivers/net/wireless/b43/tables_phy_ht.c +++ b/trunk/drivers/net/wireless/b43/tables_phy_ht.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n HT-PHY data tables - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -576,42 +574,6 @@ static const u32 b43_httab_0x24[] = { 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, }; -/* Some late-init table */ -const u32 b43_httab_0x1a_0xc0_late[] = { - 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, - 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, - 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, - 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, - 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, - 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, - 0x10390038, 0x10390035, 0x1031003a, 0x10310036, - 0x10310033, 0x1029003a, 0x10290037, 0x10290034, - 0x10290031, 0x10210039, 0x10210036, 0x10210033, - 0x10210030, 0x1019003c, 0x10190039, 0x10190036, - 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, - 0x10190028, 0x1011003a, 0x10110036, 0x10110033, - 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, - 0x10110027, 0x10110024, 0x10110022, 0x10110020, - 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, - 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, - 0x10090029, 0x10090027, 0x10090025, 0x10090023, - 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, - 0x1009001a, 0x10090018, 0x10090017, 0x10090016, - 0x10090015, 0x10090013, 0x10090012, 0x10090011, - 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, - 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, - 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, - 0x10090008, 0x10090008, 0x10090007, 0x10090007, - 0x10090007, 0x10090006, 0x10090006, 0x10090005, - 0x10090005, 0x10090005, 0x10090005, 0x10090004, - 0x10090004, 0x10090004, 0x10090004, 0x10090003, - 0x10090003, 0x10090003, 0x10090003, 0x10090003, - 0x10090003, 0x10090002, 0x10090002, 0x10090002, - 0x10090002, 0x10090002, 0x10090002, 0x10090002, - 0x10090002, 0x10090002, 0x10090001, 0x10090001, - 0x10090001, 0x10090001, 0x10090001, 0x10090001, -}; - /************************************************** * R/W ops. **************************************************/ @@ -712,51 +674,6 @@ void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value) return; } -void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...) -{ - va_list args; - u32 type, value; - unsigned int i; - - type = offset & B43_HTTAB_TYPEMASK; - offset &= 0xFFFF; - - va_start(args, num); - switch (type) { - case B43_HTTAB_8BIT: - b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); - for (i = 0; i < num; i++) { - value = va_arg(args, int); - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); - } - break; - case B43_HTTAB_16BIT: - b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); - for (i = 0; i < num; i++) { - value = va_arg(args, int); - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); - } - break; - case B43_HTTAB_32BIT: - b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); - for (i = 0; i < num; i++) { - value = va_arg(args, int); - b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, - value >> 16); - b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, - value & 0xFFFF); - } - break; - default: - B43_WARN_ON(1); - } - va_end(args); - - return; -} - void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data) { @@ -806,9 +723,6 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, } while (0) void b43_phy_ht_tables_init(struct b43_wldev *dev) { - BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) != - B43_HTTAB_1A_C0_LATE_SIZE); - httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12); httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27); httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26); diff --git a/trunk/drivers/net/wireless/b43/tables_phy_ht.h b/trunk/drivers/net/wireless/b43/tables_phy_ht.h index 1b5ef2bc770c..ea3be382c894 100644 --- a/trunk/drivers/net/wireless/b43/tables_phy_ht.h +++ b/trunk/drivers/net/wireless/b43/tables_phy_ht.h @@ -14,13 +14,9 @@ u32 b43_httab_read(struct b43_wldev *dev, u32 offset); void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, void *_data); void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value); -void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...); void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data); void b43_phy_ht_tables_init(struct b43_wldev *dev); -#define B43_HTTAB_1A_C0_LATE_SIZE 128 -extern const u32 b43_httab_0x1a_0xc0_late[]; - #endif /* B43_TABLES_PHY_HT_H_ */ diff --git a/trunk/drivers/net/wireless/b43/tables_phy_lcn.c b/trunk/drivers/net/wireless/b43/tables_phy_lcn.c index 9d484e2f79bf..40c1d0915dd3 100644 --- a/trunk/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/trunk/drivers/net/wireless/b43/tables_phy_lcn.c @@ -3,8 +3,6 @@ Broadcom B43 wireless driver IEEE 802.11n LCN-PHY data tables - Copyright (c) 2011 Rafał Miłecki - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -27,681 +25,10 @@ #include "phy_common.h" #include "phy_lcn.h" -struct b43_lcntab_tx_gain_tbl_entry { - u8 gm; - u8 pga; - u8 pad; - u8 dac; - u8 bb_mult; -}; - -/************************************************** - * Static tables. - **************************************************/ - -static const u16 b43_lcntab_0x02[] = { - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, - 0x014d, 0x014d, 0x014d, 0x014d, -}; - -static const u16 b43_lcntab_0x01[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u32 b43_lcntab_0x0b[] = { - 0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb, - 0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb, - 0x0001fea3, 0x0000024b, -}; - -static const u32 b43_lcntab_0x0c[] = { - 0x00100001, 0x00200010, 0x00300001, 0x00400010, - 0x00500022, 0x00600122, 0x00700222, 0x00800322, - 0x00900422, 0x00a00522, 0x00b00622, 0x00c00722, - 0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22, - 0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22, -}; - -static const u32 b43_lcntab_0x0d[] = { - 0x00000000, 0x00000000, 0x10000000, 0x00000000, - 0x20000000, 0x00000000, 0x30000000, 0x00000000, - 0x40000000, 0x00000000, 0x50000000, 0x00000000, - 0x60000000, 0x00000000, 0x70000000, 0x00000000, - 0x80000000, 0x00000000, 0x90000000, 0x00000008, - 0xa0000000, 0x00000008, 0xb0000000, 0x00000008, - 0xc0000000, 0x00000008, 0xd0000000, 0x00000008, - 0xe0000000, 0x00000008, 0xf0000000, 0x00000008, - 0x00000000, 0x00000009, 0x10000000, 0x00000009, - 0x20000000, 0x00000019, 0x30000000, 0x00000019, - 0x40000000, 0x00000019, 0x50000000, 0x00000019, - 0x60000000, 0x00000019, 0x70000000, 0x00000019, - 0x80000000, 0x00000019, 0x90000000, 0x00000019, - 0xa0000000, 0x00000019, 0xb0000000, 0x00000019, - 0xc0000000, 0x00000019, 0xd0000000, 0x00000019, - 0xe0000000, 0x00000019, 0xf0000000, 0x00000019, - 0x00000000, 0x0000001a, 0x10000000, 0x0000001a, - 0x20000000, 0x0000001a, 0x30000000, 0x0000001a, - 0x40000000, 0x0000001a, 0x50000000, 0x00000002, - 0x60000000, 0x00000002, 0x70000000, 0x00000002, - 0x80000000, 0x00000002, 0x90000000, 0x00000002, - 0xa0000000, 0x00000002, 0xb0000000, 0x00000002, - 0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a, - 0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a, - 0x00000000, 0x0000000b, 0x10000000, 0x0000000b, - 0x20000000, 0x0000000b, 0x30000000, 0x0000000b, - 0x40000000, 0x0000000b, 0x50000000, 0x0000001b, - 0x60000000, 0x0000001b, 0x70000000, 0x0000001b, - 0x80000000, 0x0000001b, 0x90000000, 0x0000001b, - 0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b, - 0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b, - 0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b, - 0x00000000, 0x0000001c, 0x10000000, 0x0000001c, - 0x20000000, 0x0000001c, 0x30000000, 0x0000001c, - 0x40000000, 0x0000001c, 0x50000000, 0x0000001c, - 0x60000000, 0x0000001c, 0x70000000, 0x0000001c, - 0x80000000, 0x0000001c, 0x90000000, 0x0000001c, -}; - -static const u16 b43_lcntab_0x0e[] = { - 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, - 0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c, - 0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092, - 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198, - 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, - 0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4, - 0x01a5, 0x0000, -}; - -static const u16 b43_lcntab_0x0f[] = { - 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, - 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, - 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, - 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, - 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, - 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, - 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, - 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, - 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, - 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, - 0x000a, 0x0009, 0x0006, 0x0005, -}; - -static const u16 b43_lcntab_0x10[] = { - 0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036, - 0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f, - 0x005f, 0x0036, 0x0029, 0x001f, -}; - -static const u16 b43_lcntab_0x11[] = { - 0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007, - 0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005, - 0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, - 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, - 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, - 0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000, -}; - -static const u32 b43_lcntab_0x12[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000004, 0x00000000, 0x00000004, 0x00000008, - 0x00000001, 0x00000005, 0x00000009, 0x0000000d, - 0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d, - 0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f, - 0x000000cf, 0x000000d3, 0x00000113, 0x00000513, - 0x00000913, 0x00000953, 0x00000d53, 0x00001153, - 0x00001193, 0x00005193, 0x00009193, 0x0000d193, - 0x00011193, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000004, - 0x00000000, 0x00000004, 0x00000008, 0x00000001, - 0x00000005, 0x00000009, 0x0000000d, 0x0000004d, - 0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d, - 0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf, - 0x000000d3, 0x00000113, 0x00000513, 0x00000913, - 0x00000953, 0x00000d53, 0x00001153, 0x00005153, - 0x00009153, 0x0000d153, 0x00011153, 0x00015153, - 0x00019153, 0x0001d153, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; - -static const u16 b43_lcntab_0x14[] = { - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003, - 0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, -}; - -static const u16 b43_lcntab_0x17[] = { - 0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0, - 0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0, - 0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c, - 0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c, - 0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340, - 0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104, - 0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104, - 0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186, - 0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104, - 0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4, - 0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186, - 0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be, - 0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036, - 0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6, - 0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288, - 0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6, - 0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8, - 0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798, - 0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6, - 0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288, - 0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a, - 0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288, - 0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360, - 0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc, - 0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510, - 0x05b2, 0x0654, 0x0654, 0x06f6, -}; - -static const u16 b43_lcntab_0x00[] = { - 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, - 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, - 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600, - 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, - 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, - 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u32 b43_lcntab_0x18[] = { - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, - 0x00080000, 0x00080000, 0x00080000, 0x00080000, -}; - -/************************************************** - * TX gain. - **************************************************/ - -const struct b43_lcntab_tx_gain_tbl_entry - b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = { - { 0x03, 0x00, 0x1f, 0x0, 0x48 }, - { 0x03, 0x00, 0x1f, 0x0, 0x46 }, - { 0x03, 0x00, 0x1f, 0x0, 0x44 }, - { 0x03, 0x00, 0x1e, 0x0, 0x43 }, - { 0x03, 0x00, 0x1d, 0x0, 0x44 }, - { 0x03, 0x00, 0x1c, 0x0, 0x44 }, - { 0x03, 0x00, 0x1b, 0x0, 0x45 }, - { 0x03, 0x00, 0x1a, 0x0, 0x46 }, - { 0x03, 0x00, 0x19, 0x0, 0x46 }, - { 0x03, 0x00, 0x18, 0x0, 0x47 }, - { 0x03, 0x00, 0x17, 0x0, 0x48 }, - { 0x03, 0x00, 0x17, 0x0, 0x46 }, - { 0x03, 0x00, 0x16, 0x0, 0x47 }, - { 0x03, 0x00, 0x15, 0x0, 0x48 }, - { 0x03, 0x00, 0x15, 0x0, 0x46 }, - { 0x03, 0x00, 0x15, 0x0, 0x44 }, - { 0x03, 0x00, 0x15, 0x0, 0x42 }, - { 0x03, 0x00, 0x15, 0x0, 0x40 }, - { 0x03, 0x00, 0x15, 0x0, 0x3f }, - { 0x03, 0x00, 0x14, 0x0, 0x40 }, - { 0x03, 0x00, 0x13, 0x0, 0x41 }, - { 0x03, 0x00, 0x13, 0x0, 0x40 }, - { 0x03, 0x00, 0x12, 0x0, 0x41 }, - { 0x03, 0x00, 0x12, 0x0, 0x40 }, - { 0x03, 0x00, 0x11, 0x0, 0x41 }, - { 0x03, 0x00, 0x11, 0x0, 0x40 }, - { 0x03, 0x00, 0x10, 0x0, 0x41 }, - { 0x03, 0x00, 0x10, 0x0, 0x40 }, - { 0x03, 0x00, 0x10, 0x0, 0x3e }, - { 0x03, 0x00, 0x10, 0x0, 0x3c }, - { 0x03, 0x00, 0x10, 0x0, 0x3a }, - { 0x03, 0x00, 0x0f, 0x0, 0x3d }, - { 0x03, 0x00, 0x0f, 0x0, 0x3b }, - { 0x03, 0x00, 0x0e, 0x0, 0x3d }, - { 0x03, 0x00, 0x0e, 0x0, 0x3c }, - { 0x03, 0x00, 0x0e, 0x0, 0x3a }, - { 0x03, 0x00, 0x0d, 0x0, 0x3c }, - { 0x03, 0x00, 0x0d, 0x0, 0x3b }, - { 0x03, 0x00, 0x0c, 0x0, 0x3e }, - { 0x03, 0x00, 0x0c, 0x0, 0x3c }, - { 0x03, 0x00, 0x0c, 0x0, 0x3a }, - { 0x03, 0x00, 0x0b, 0x0, 0x3e }, - { 0x03, 0x00, 0x0b, 0x0, 0x3c }, - { 0x03, 0x00, 0x0b, 0x0, 0x3b }, - { 0x03, 0x00, 0x0b, 0x0, 0x39 }, - { 0x03, 0x00, 0x0a, 0x0, 0x3d }, - { 0x03, 0x00, 0x0a, 0x0, 0x3b }, - { 0x03, 0x00, 0x0a, 0x0, 0x39 }, - { 0x03, 0x00, 0x09, 0x0, 0x3e }, - { 0x03, 0x00, 0x09, 0x0, 0x3c }, - { 0x03, 0x00, 0x09, 0x0, 0x3a }, - { 0x03, 0x00, 0x09, 0x0, 0x39 }, - { 0x03, 0x00, 0x08, 0x0, 0x3e }, - { 0x03, 0x00, 0x08, 0x0, 0x3c }, - { 0x03, 0x00, 0x08, 0x0, 0x3a }, - { 0x03, 0x00, 0x08, 0x0, 0x39 }, - { 0x03, 0x00, 0x08, 0x0, 0x37 }, - { 0x03, 0x00, 0x07, 0x0, 0x3d }, - { 0x03, 0x00, 0x07, 0x0, 0x3c }, - { 0x03, 0x00, 0x07, 0x0, 0x3a }, - { 0x03, 0x00, 0x07, 0x0, 0x38 }, - { 0x03, 0x00, 0x07, 0x0, 0x37 }, - { 0x03, 0x00, 0x06, 0x0, 0x3e }, - { 0x03, 0x00, 0x06, 0x0, 0x3c }, - { 0x03, 0x00, 0x06, 0x0, 0x3a }, - { 0x03, 0x00, 0x06, 0x0, 0x39 }, - { 0x03, 0x00, 0x06, 0x0, 0x37 }, - { 0x03, 0x00, 0x06, 0x0, 0x36 }, - { 0x03, 0x00, 0x06, 0x0, 0x34 }, - { 0x03, 0x00, 0x05, 0x0, 0x3d }, - { 0x03, 0x00, 0x05, 0x0, 0x3b }, - { 0x03, 0x00, 0x05, 0x0, 0x39 }, - { 0x03, 0x00, 0x05, 0x0, 0x38 }, - { 0x03, 0x00, 0x05, 0x0, 0x36 }, - { 0x03, 0x00, 0x05, 0x0, 0x35 }, - { 0x03, 0x00, 0x05, 0x0, 0x33 }, - { 0x03, 0x00, 0x04, 0x0, 0x3e }, - { 0x03, 0x00, 0x04, 0x0, 0x3c }, - { 0x03, 0x00, 0x04, 0x0, 0x3a }, - { 0x03, 0x00, 0x04, 0x0, 0x39 }, - { 0x03, 0x00, 0x04, 0x0, 0x37 }, - { 0x03, 0x00, 0x04, 0x0, 0x36 }, - { 0x03, 0x00, 0x04, 0x0, 0x34 }, - { 0x03, 0x00, 0x04, 0x0, 0x33 }, - { 0x03, 0x00, 0x04, 0x0, 0x31 }, - { 0x03, 0x00, 0x04, 0x0, 0x30 }, - { 0x03, 0x00, 0x04, 0x0, 0x2e }, - { 0x03, 0x00, 0x03, 0x0, 0x3c }, - { 0x03, 0x00, 0x03, 0x0, 0x3a }, - { 0x03, 0x00, 0x03, 0x0, 0x39 }, - { 0x03, 0x00, 0x03, 0x0, 0x37 }, - { 0x03, 0x00, 0x03, 0x0, 0x36 }, - { 0x03, 0x00, 0x03, 0x0, 0x34 }, - { 0x03, 0x00, 0x03, 0x0, 0x33 }, - { 0x03, 0x00, 0x03, 0x0, 0x31 }, - { 0x03, 0x00, 0x03, 0x0, 0x30 }, - { 0x03, 0x00, 0x03, 0x0, 0x2e }, - { 0x03, 0x00, 0x03, 0x0, 0x2d }, - { 0x03, 0x00, 0x03, 0x0, 0x2c }, - { 0x03, 0x00, 0x03, 0x0, 0x2b }, - { 0x03, 0x00, 0x03, 0x0, 0x29 }, - { 0x03, 0x00, 0x02, 0x0, 0x3d }, - { 0x03, 0x00, 0x02, 0x0, 0x3b }, - { 0x03, 0x00, 0x02, 0x0, 0x39 }, - { 0x03, 0x00, 0x02, 0x0, 0x38 }, - { 0x03, 0x00, 0x02, 0x0, 0x36 }, - { 0x03, 0x00, 0x02, 0x0, 0x35 }, - { 0x03, 0x00, 0x02, 0x0, 0x33 }, - { 0x03, 0x00, 0x02, 0x0, 0x32 }, - { 0x03, 0x00, 0x02, 0x0, 0x30 }, - { 0x03, 0x00, 0x02, 0x0, 0x2f }, - { 0x03, 0x00, 0x02, 0x0, 0x2e }, - { 0x03, 0x00, 0x02, 0x0, 0x2c }, - { 0x03, 0x00, 0x02, 0x0, 0x2b }, - { 0x03, 0x00, 0x02, 0x0, 0x2a }, - { 0x03, 0x00, 0x02, 0x0, 0x29 }, - { 0x03, 0x00, 0x02, 0x0, 0x27 }, - { 0x03, 0x00, 0x02, 0x0, 0x26 }, - { 0x03, 0x00, 0x02, 0x0, 0x25 }, - { 0x03, 0x00, 0x02, 0x0, 0x24 }, - { 0x03, 0x00, 0x02, 0x0, 0x23 }, - { 0x03, 0x00, 0x02, 0x0, 0x22 }, - { 0x03, 0x00, 0x02, 0x0, 0x21 }, - { 0x03, 0x00, 0x02, 0x0, 0x20 }, - { 0x03, 0x00, 0x01, 0x0, 0x3f }, - { 0x03, 0x00, 0x01, 0x0, 0x3d }, - { 0x03, 0x00, 0x01, 0x0, 0x3b }, - { 0x03, 0x00, 0x01, 0x0, 0x39 }, -}; - -/************************************************** - * SW control. - **************************************************/ - -const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = { - 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, - 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, - 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, - 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, - 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, - 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, - 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, - 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, - 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, - 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, - 0x0002, 0x0008, 0x0004, 0x0001, -}; - -/************************************************** - * R/W ops. - **************************************************/ - -u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset) -{ - u32 type, value; - - type = offset & B43_LCNTAB_TYPEMASK; - offset &= ~B43_LCNTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - switch (type) { - case B43_LCNTAB_8BIT: - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF; - break; - case B43_LCNTAB_16BIT: - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); - break; - case B43_LCNTAB_32BIT: - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); - value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16); - break; - default: - B43_WARN_ON(1); - value = 0; - } - - return value; -} - -void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, void *_data) -{ - u32 type; - u8 *data = _data; - unsigned int i; - - type = offset & B43_LCNTAB_TYPEMASK; - offset &= ~B43_LCNTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - - for (i = 0; i < nr_elements; i++) { - switch (type) { - case B43_LCNTAB_8BIT: - *data = b43_phy_read(dev, - B43_PHY_LCN_TABLE_DATALO) & 0xFF; - data++; - break; - case B43_LCNTAB_16BIT: - *((u16 *)data) = b43_phy_read(dev, - B43_PHY_LCN_TABLE_DATALO); - data += 2; - break; - case B43_LCNTAB_32BIT: - *((u32 *)data) = b43_phy_read(dev, - B43_PHY_LCN_TABLE_DATALO); - *((u32 *)data) |= (b43_phy_read(dev, - B43_PHY_LCN_TABLE_DATAHI) << 16); - data += 4; - break; - default: - B43_WARN_ON(1); - } - } -} - -void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value) -{ - u32 type; - - type = offset & B43_LCNTAB_TYPEMASK; - offset &= 0xFFFF; - - switch (type) { - case B43_LCNTAB_8BIT: - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); - break; - case B43_LCNTAB_16BIT: - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); - break; - case B43_LCNTAB_32BIT: - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF); - break; - default: - B43_WARN_ON(1); - } - - return; -} - -void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, const void *_data) -{ - u32 type, value; - const u8 *data = _data; - unsigned int i; - - type = offset & B43_LCNTAB_TYPEMASK; - offset &= ~B43_LCNTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); - - for (i = 0; i < nr_elements; i++) { - switch (type) { - case B43_LCNTAB_8BIT: - value = *data; - data++; - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); - break; - case B43_LCNTAB_16BIT: - value = *((u16 *)data); - data += 2; - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); - break; - case B43_LCNTAB_32BIT: - value = *((u32 *)data); - data += 4; - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, - value >> 16); - b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, - value & 0xFFFF); - break; - default: - B43_WARN_ON(1); - } - } -} - /************************************************** * Tables ops. **************************************************/ -#define lcntab_upload(dev, offset, data) do { \ - b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \ - } while (0) -static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev) -{ - lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02); - lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01); - lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b); - lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c); - lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d); - lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e); - lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f); - lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10); - lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11); - lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12); - lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14); - lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17); - lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00); - lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); -} - -void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, - const struct b43_lcntab_tx_gain_tbl_entry *gain_table) -{ - u32 i; - u32 val; - - u16 pa_gain = 0x70; - if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) - pa_gain = 0x10; - - for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) { - val = ((pa_gain << 24) | - (gain_table[i].pad << 16) | - (gain_table[i].pga << 8) | - gain_table[i].gm); - b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val); - - /* brcmsmac doesn't maskset, we follow newer wl here */ - val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i)); - val &= 0x000fffff; - val |= ((gain_table[i].dac << 28) | - (gain_table[i].bb_mult << 20)); - b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val); - } -} - -/* Not implemented in brcmsmac, noticed in wl in MMIO dump */ -static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev) -{ - int i; - u32 tmp; - for (i = 0; i < 128; i++) { - tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i)); - b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp); - } -} - -/* wlc_lcnphy_clear_papd_comptable */ -static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev) -{ - u8 i; - - for (i = 0; i < 0x80; i++) - b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000); -} - -/* wlc_lcnphy_tbl_init */ void b43_phy_lcn_tables_init(struct b43_wldev *dev) { - struct ssb_sprom *sprom = dev->dev->bus_sprom; - - b43_phy_lcn_upload_static_tables(dev); - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (sprom->boardflags_lo & B43_BFL_EXTLNA) - b43_phy_lcn_load_tx_gain_tab(dev, - b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); - else - b43err(dev->wl, - "TX gain table unknown for this card\n"); - } - - if (sprom->boardflags_lo & B43_BFL_FEM && - !(sprom->boardflags_hi & B43_BFH_FEM_BT)) - b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0), - ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0), - b43_lcntab_sw_ctl_4313_epa_rev0); - else - b43err(dev->wl, "SW ctl table is unknown for this card\n"); - - /* TODO: various tables ops here */ - b43_phy_lcn_rewrite_tables(dev); - b43_phy_lcn_clean_papd_comp_table(dev); } diff --git a/trunk/drivers/net/wireless/b43/tables_phy_lcn.h b/trunk/drivers/net/wireless/b43/tables_phy_lcn.h index caff9db6831f..5e31b15b81ec 100644 --- a/trunk/drivers/net/wireless/b43/tables_phy_lcn.h +++ b/trunk/drivers/net/wireless/b43/tables_phy_lcn.h @@ -1,24 +1,6 @@ #ifndef B43_TABLES_PHY_LCN_H_ #define B43_TABLES_PHY_LCN_H_ -/* The LCN-PHY tables. */ -#define B43_LCNTAB_TYPEMASK 0xF0000000 -#define B43_LCNTAB_8BIT 0x10000000 -#define B43_LCNTAB_16BIT 0x20000000 -#define B43_LCNTAB_32BIT 0x30000000 -#define B43_LCNTAB8(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_8BIT) -#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT) -#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT) - -#define B43_LCNTAB_TX_GAIN_SIZE 128 - -u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset); -void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, void *_data); -void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value); -void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, const void *_data); - void b43_phy_lcn_tables_init(struct b43_wldev *dev); #endif /* B43_TABLES_PHY_LCN_H_ */ diff --git a/trunk/drivers/net/wireless/b43/xmit.c b/trunk/drivers/net/wireless/b43/xmit.c index b8de62c22479..b74f25ec1ab4 100644 --- a/trunk/drivers/net/wireless/b43/xmit.c +++ b/trunk/drivers/net/wireless/b43/xmit.c @@ -337,19 +337,12 @@ int b43_generate_txhdr(struct b43_wldev *dev, memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); } } - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp), + if (b43_is_old_txhdr_format(dev)) { + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), plcp_fragment_len, rate); - break; - case B43_FW_HDR_351: - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), - plcp_fragment_len, rate); - break; - case B43_FW_HDR_410: - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp), + } else { + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), plcp_fragment_len, rate); - break; } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), plcp_fragment_len, rate_fb); @@ -422,10 +415,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; - struct ieee80211_hdr *uninitialized_var(hdr); + struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; - struct b43_plcp_hdr6 *uninitialized_var(plcp); + struct b43_plcp_hdr6 *plcp; struct ieee80211_rate *rts_cts_rate; rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); @@ -436,21 +429,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *uninitialized_var(cts); + struct ieee80211_cts *cts; - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - cts = (struct ieee80211_cts *) - (txhdr->format_598.rts_frame); - break; - case B43_FW_HDR_351: + if (b43_is_old_txhdr_format(dev)) { cts = (struct ieee80211_cts *) - (txhdr->format_351.rts_frame); - break; - case B43_FW_HDR_410: + (txhdr->old_format.rts_frame); + } else { cts = (struct ieee80211_cts *) - (txhdr->format_410.rts_frame); - break; + (txhdr->new_format.rts_frame); } ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -458,21 +444,14 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { - struct ieee80211_rts *uninitialized_var(rts); + struct ieee80211_rts *rts; - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - rts = (struct ieee80211_rts *) - (txhdr->format_598.rts_frame); - break; - case B43_FW_HDR_351: + if (b43_is_old_txhdr_format(dev)) { rts = (struct ieee80211_rts *) - (txhdr->format_351.rts_frame); - break; - case B43_FW_HDR_410: + (txhdr->old_format.rts_frame); + } else { rts = (struct ieee80211_rts *) - (txhdr->format_410.rts_frame); - break; + (txhdr->new_format.rts_frame); } ieee80211_rts_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -483,36 +462,22 @@ int b43_generate_txhdr(struct b43_wldev *dev, len += FCS_LEN; /* Generate the PLCP headers for the RTS/CTS frame */ - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - plcp = &txhdr->format_598.rts_plcp; - break; - case B43_FW_HDR_351: - plcp = &txhdr->format_351.rts_plcp; - break; - case B43_FW_HDR_410: - plcp = &txhdr->format_410.rts_plcp; - break; - } + if (b43_is_old_txhdr_format(dev)) + plcp = &txhdr->old_format.rts_plcp; + else + plcp = &txhdr->new_format.rts_plcp; b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate); plcp = &txhdr->rts_plcp_fb; b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate_fb); - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: + if (b43_is_old_txhdr_format(dev)) { hdr = (struct ieee80211_hdr *) - (&txhdr->format_598.rts_frame); - break; - case B43_FW_HDR_351: - hdr = (struct ieee80211_hdr *) - (&txhdr->format_351.rts_frame); - break; - case B43_FW_HDR_410: + (&txhdr->old_format.rts_frame); + } else { hdr = (struct ieee80211_hdr *) - (&txhdr->format_410.rts_frame); - break; + (&txhdr->new_format.rts_frame); } txhdr->rts_dur_fb = hdr->duration_id; @@ -540,17 +505,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, } /* Magic cookie */ - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - txhdr->format_598.cookie = cpu_to_le16(cookie); - break; - case B43_FW_HDR_351: - txhdr->format_351.cookie = cpu_to_le16(cookie); - break; - case B43_FW_HDR_410: - txhdr->format_410.cookie = cpu_to_le16(cookie); - break; - } + if (b43_is_old_txhdr_format(dev)) + txhdr->old_format.cookie = cpu_to_le16(cookie); + else + txhdr->new_format.cookie = cpu_to_le16(cookie); if (phy->type == B43_PHYTYPE_N) { txhdr->phy_ctl1 = @@ -653,9 +611,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) struct ieee80211_hdr *wlhdr; const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; __le16 fctl; - u16 phystat0, phystat3; - u16 uninitialized_var(chanstat), uninitialized_var(mactime); - u32 uninitialized_var(macstat); + u16 phystat0, phystat3, chanstat, mactime; + u32 macstat; u16 chanid; u16 phytype; int padding; @@ -665,19 +622,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* Get metadata about the frame from the header. */ phystat0 = le16_to_cpu(rxhdr->phy_status0); phystat3 = le16_to_cpu(rxhdr->phy_status3); - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - macstat = le32_to_cpu(rxhdr->format_598.mac_status); - mactime = le16_to_cpu(rxhdr->format_598.mac_time); - chanstat = le16_to_cpu(rxhdr->format_598.channel); - break; - case B43_FW_HDR_410: - case B43_FW_HDR_351: - macstat = le32_to_cpu(rxhdr->format_351.mac_status); - mactime = le16_to_cpu(rxhdr->format_351.mac_time); - chanstat = le16_to_cpu(rxhdr->format_351.channel); - break; - } + macstat = le32_to_cpu(rxhdr->mac_status); + mactime = le16_to_cpu(rxhdr->mac_time); + chanstat = le16_to_cpu(rxhdr->channel); phytype = chanstat & B43_RX_CHAN_PHYTYPE; if (unlikely(macstat & B43_RX_MAC_FCSERR)) { @@ -797,7 +744,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) break; case B43_PHYTYPE_N: case B43_PHYTYPE_LP: - case B43_PHYTYPE_HT: /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) { diff --git a/trunk/drivers/net/wireless/b43/xmit.h b/trunk/drivers/net/wireless/b43/xmit.h index f6e8bc436d5a..42debb5cd6fa 100644 --- a/trunk/drivers/net/wireless/b43/xmit.h +++ b/trunk/drivers/net/wireless/b43/xmit.h @@ -46,24 +46,7 @@ struct b43_txhdr { __le32 timeout; /* Timeout */ union { - /* Tested with 598.314, 644.1001 and 666.2 */ - struct { - __le16 mimo_antenna; /* MIMO antenna select */ - __le16 preload_size; /* Preload size */ - PAD_BYTES(2); - __le16 cookie; /* TX frame cookie */ - __le16 tx_status; /* TX status */ - __le16 max_n_mpdus; - __le16 max_a_bytes_mrt; - __le16 max_a_bytes_fbr; - __le16 min_m_bytes; - struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ - __u8 rts_frame[16]; /* The RTS frame (if used) */ - PAD_BYTES(2); - struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } format_598 __packed; - - /* Tested with 410.2160, 478.104 and 508.* */ + /* The new r410 format. */ struct { __le16 mimo_antenna; /* MIMO antenna select */ __le16 preload_size; /* Preload size */ @@ -74,9 +57,9 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } format_410 __packed; + } new_format __packed; - /* Tested with 351.126 */ + /* The old r351 format. */ struct { PAD_BYTES(2); __le16 cookie; /* TX frame cookie */ @@ -85,7 +68,7 @@ struct b43_txhdr { __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } format_351 __packed; + } old_format __packed; } __packed; } __packed; @@ -183,18 +166,19 @@ struct b43_tx_legacy_rate_phy_ctl_entry { #define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */ +/* r351 firmware compatibility stuff. */ +static inline +bool b43_is_old_txhdr_format(struct b43_wldev *dev) +{ + return (dev->fw.rev <= 351); +} + static inline size_t b43_txhdr_size(struct b43_wldev *dev) { - switch (dev->fw.hdr_format) { - case B43_FW_HDR_598: - return 112 + sizeof(struct b43_plcp_hdr6); - case B43_FW_HDR_410: - return 104 + sizeof(struct b43_plcp_hdr6); - case B43_FW_HDR_351: + if (b43_is_old_txhdr_format(dev)) return 100 + sizeof(struct b43_plcp_hdr6); - } - return 0; + return 104 + sizeof(struct b43_plcp_hdr6); } @@ -250,23 +234,9 @@ struct b43_rxhdr_fw4 { } __packed; __le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status3; /* PHY RX Status 3 */ - union { - /* Tested with 598.314, 644.1001 and 666.2 */ - struct { - __le16 phy_status4; /* PHY RX Status 4 */ - __le16 phy_status5; /* PHY RX Status 5 */ - __le32 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; - } format_598 __packed; - - /* Tested with 351.126, 410.2160, 478.104 and 508.* */ - struct { - __le32 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; - } format_351 __packed; - } __packed; + __le32 mac_status; /* MAC RX status */ + __le16 mac_time; + __le16 channel; } __packed; /* PHY RX Status 0 */ diff --git a/trunk/drivers/net/wireless/b43legacy/b43legacy.h b/trunk/drivers/net/wireless/b43legacy/b43legacy.h index 12b518251581..ad4e743e4765 100644 --- a/trunk/drivers/net/wireless/b43legacy/b43legacy.h +++ b/trunk/drivers/net/wireless/b43legacy/b43legacy.h @@ -22,6 +22,10 @@ #include "phy.h" +/* The unique identifier of the firmware that's officially supported by this + * driver version. */ +#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10" + #define B43legacy_IRQWAIT_MAX_RETRIES 20 /* MMIO offsets */ diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index 468d1836548e..aae8dfcb852e 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -60,6 +60,7 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); MODULE_FIRMWARE("b43legacy/ucode2.fw"); MODULE_FIRMWARE("b43legacy/ucode4.fw"); @@ -3946,7 +3947,8 @@ static void b43legacy_print_driverinfo(void) feat_dma = "D"; #endif printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " - "[ Features: %s%s%s%s ]\n", + "[ Features: %s%s%s%s, Firmware-ID: " + B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", feat_pci, feat_leds, feat_pio, feat_dma); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c index 4766c3a1a2f6..ccdbed567171 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -43,8 +43,6 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 6 @@ -78,21 +76,21 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 1000 series */ static void iwl1000_nic_config(struct iwl_priv *priv) { /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); /* Setting digital SVR for 1000 card to 1.32V */ /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG, + iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, APMG_SVR_DIGITAL_VOLTAGE_1_32, ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } @@ -129,39 +127,43 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl1000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl1000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl1000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c index 913f2a228527..54d931d614fb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -44,8 +44,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 6 @@ -80,8 +78,8 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 2000 series */ @@ -90,7 +88,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); if (priv->cfg->iq_invert) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } @@ -126,40 +124,44 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl2000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl2000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl2000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -177,7 +179,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -198,7 +200,7 @@ static struct iwl_lib_ops iwl2030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -282,12 +284,6 @@ struct iwl_cfg iwl2000_2bg_cfg = { IWL_DEVICE_2000, }; -struct iwl_cfg iwl2000_2bgn_d_cfg = { - .name = "2000D Series 2x2 BGN", - IWL_DEVICE_2000, - .ht_params = &iwl2000_ht_params, -}; - #define IWL_DEVICE_2030 \ .fw_name_pre = IWL2030_FW_PRE, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cb4d69e0c37..a9adee5634d8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -46,8 +46,6 @@ #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-trans.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 @@ -70,18 +68,18 @@ static void iwl5000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* W/A : NIC is stuck in a reset state after Early PCIe power off * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } static struct iwl_sensitivity_ranges iwl5000_sensitivity = { @@ -141,13 +139,13 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv) s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - iwl_temp_calib_to_offset(priv); - hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; + priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; } static void iwl5000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; } static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) @@ -157,34 +155,38 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl5000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl5000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl5000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -196,34 +198,38 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl5150_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl5150_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl5150_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -308,7 +314,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl5000_lib = { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index 2a98e65ca84c..339de88d9ae2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -45,8 +45,6 @@ #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-trans.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 @@ -76,15 +74,15 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } static void iwl6050_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); } @@ -92,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_6050_1x2); } @@ -106,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) /* no locking required for register write */ if (priv->cfg->pa_type == IWL_PA_INTERNAL) { /* 2x2 IPA phy type */ - iwl_write32(bus(priv), CSR_GP_DRIVER_REG, + iwl_write32(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* do additional nic configuration if needed */ @@ -146,41 +144,45 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl6000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl6000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl6000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -253,7 +255,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl6000_lib = { @@ -270,7 +272,7 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -292,7 +294,7 @@ static struct iwl_lib_ops iwl6030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -393,12 +395,6 @@ struct iwl_cfg iwl6005_2bg_cfg = { IWL_DEVICE_6005, }; -struct iwl_cfg iwl6005_2agn_sff_cfg = { - .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN", - IWL_DEVICE_6005, - .ht_params = &iwl6000_ht_params, -}; - #define IWL_DEVICE_6030 \ .fw_name_pre = IWL6030_FW_PRE, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index b725f6970dee..1789e3af8101 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -93,12 +93,12 @@ int iwl_send_calib_results(struct iwl_priv *priv) }; for (i = 0; i < IWL_CALIB_MAX; i++) { - if ((BIT(i) & hw_params(priv).calib_init_cfg) && + if ((BIT(i) & priv->hw_params.calib_init_cfg) && priv->calib_results[i].buf) { hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = iwl_trans_send_cmd(trans(priv), &hcmd); + ret = trans_send_cmd(&priv->trans, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", ret, i); @@ -174,7 +174,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; data = &(priv->sensitivity_data); @@ -357,7 +357,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; data = &(priv->sensitivity_data); @@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -573,7 +573,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -581,7 +581,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) int ret = 0; int i; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; if (priv->disable_sens_cal) return; @@ -658,13 +658,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rx_info = &priv->statistics.rx_non_phy; ofdm = &priv->statistics.rx_ofdm; cck = &priv->statistics.rx_cck; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -688,7 +688,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); @@ -821,21 +821,21 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * To be safe, simply mask out any chains that we know * are not on the device. */ - active_chains &= hw_params(priv).valid_rx_ant; + active_chains &= priv->hw_params.valid_rx_ant; num_tx_chains = 0; for (i = 0; i < NUM_RX_CHAINS; i++) { /* loops on all the bits of * priv->hw_setting.valid_tx_ant */ u8 ant_msk = (1 << i); - if (!(hw_params(priv).valid_tx_ant & ant_msk)) + if (!(priv->hw_params.valid_tx_ant & ant_msk)) continue; num_tx_chains++; if (data->disconn_array[i] == 0) /* there is a Tx antenna connected */ break; - if (num_tx_chains == hw_params(priv).tx_chains_num && + if (num_tx_chains == priv->hw_params.tx_chains_num && data->disconn_array[i]) { /* * If all chains are disconnected @@ -852,13 +852,12 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, } } - if (active_chains != hw_params(priv).valid_rx_ant && + if (active_chains != priv->hw_params.valid_rx_ant && active_chains != priv->chain_noise_data.active_chains) IWL_DEBUG_CALIB(priv, "Detected that not all antennas are connected! " "Connected: %#x, valid: %#x.\n", - active_chains, - hw_params(priv).valid_rx_ant); + active_chains, priv->hw_params.valid_rx_ant); /* Save for use within RXON, TX, SCAN commands, etc. */ data->active_chains = active_chains; @@ -918,7 +917,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, priv->phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; - iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD, + trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_ASYNC, sizeof(cmd), &cmd); data->radio_write = 1; @@ -976,13 +975,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rx_info = &priv->statistics.rx_non_phy; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -997,7 +996,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", rxon_chnum, rxon_band24); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -1016,7 +1015,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); data->beacon_count++; @@ -1047,7 +1046,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) priv->cfg->bt_params->advanced_bt_coexist) { /* Disable disconnected antenna algorithm for advanced bt coex, assuming valid antennas are connected */ - data->active_chains = hw_params(priv).valid_rx_ant; + data->active_chains = priv->hw_params.valid_rx_ant; for (i = 0; i < NUM_RX_CHAINS; i++) if (!(data->active_chains & (1<disconn_array[i] = 1; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index c62ddc2a31bd..b8347db850e7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -195,7 +195,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, } static void -iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, +iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *txp, s8 max_txpower_avg) { @@ -235,7 +235,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ ? # x " " : "") -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) { struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; int idx, entries; @@ -294,6 +294,6 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; - iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); + iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 33951a11327d..47c43042ba4f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -95,4 +95,17 @@ #define IWLAGN_NUM_AMPDU_QUEUES 9 #define IWLAGN_FIRST_AMPDU_QUEUE 11 +/* Fixed (non-configurable) rx data from phy */ + +/** + * struct iwlagn_schedq_bc_tbl scheduler byte count table + * base physical address provided by SCD_DRAM_BASE_ADDR + * @tfd_offset 0-12 - tx command byte count + * 12-16 - station index + */ +struct iwlagn_scd_bc_tbl { + __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; +} __packed; + + #endif /* __iwl_agn_hw_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 13018872f776..4edb6cfc5488 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -40,7 +40,449 @@ #include "iwl-agn.h" #include "iwl-sta.h" #include "iwl-trans.h" -#include "iwl-shared.h" + +static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) +{ + return le32_to_cpup((__le32 *)&tx_resp->status + + tx_resp->frame_count) & MAX_SN; +} + +static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_POSTPONE_DELAY: + priv->reply_tx_stats.pp_delay++; + break; + case TX_STATUS_POSTPONE_FEW_BYTES: + priv->reply_tx_stats.pp_few_bytes++; + break; + case TX_STATUS_POSTPONE_BT_PRIO: + priv->reply_tx_stats.pp_bt_prio++; + break; + case TX_STATUS_POSTPONE_QUIET_PERIOD: + priv->reply_tx_stats.pp_quiet_period++; + break; + case TX_STATUS_POSTPONE_CALC_TTAK: + priv->reply_tx_stats.pp_calc_ttak++; + break; + case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: + priv->reply_tx_stats.int_crossed_retry++; + break; + case TX_STATUS_FAIL_SHORT_LIMIT: + priv->reply_tx_stats.short_limit++; + break; + case TX_STATUS_FAIL_LONG_LIMIT: + priv->reply_tx_stats.long_limit++; + break; + case TX_STATUS_FAIL_FIFO_UNDERRUN: + priv->reply_tx_stats.fifo_underrun++; + break; + case TX_STATUS_FAIL_DRAIN_FLOW: + priv->reply_tx_stats.drain_flow++; + break; + case TX_STATUS_FAIL_RFKILL_FLUSH: + priv->reply_tx_stats.rfkill_flush++; + break; + case TX_STATUS_FAIL_LIFE_EXPIRE: + priv->reply_tx_stats.life_expire++; + break; + case TX_STATUS_FAIL_DEST_PS: + priv->reply_tx_stats.dest_ps++; + break; + case TX_STATUS_FAIL_HOST_ABORTED: + priv->reply_tx_stats.host_abort++; + break; + case TX_STATUS_FAIL_BT_RETRY: + priv->reply_tx_stats.bt_retry++; + break; + case TX_STATUS_FAIL_STA_INVALID: + priv->reply_tx_stats.sta_invalid++; + break; + case TX_STATUS_FAIL_FRAG_DROPPED: + priv->reply_tx_stats.frag_drop++; + break; + case TX_STATUS_FAIL_TID_DISABLE: + priv->reply_tx_stats.tid_disable++; + break; + case TX_STATUS_FAIL_FIFO_FLUSHED: + priv->reply_tx_stats.fifo_flush++; + break; + case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: + priv->reply_tx_stats.insuff_cf_poll++; + break; + case TX_STATUS_FAIL_PASSIVE_NO_RX: + priv->reply_tx_stats.fail_hw_drop++; + break; + case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: + priv->reply_tx_stats.sta_color_mismatch++; + break; + default: + priv->reply_tx_stats.unknown++; + break; + } +} + +static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= AGG_TX_STATUS_MSK; + + switch (status) { + case AGG_TX_STATE_UNDERRUN_MSK: + priv->reply_agg_tx_stats.underrun++; + break; + case AGG_TX_STATE_BT_PRIO_MSK: + priv->reply_agg_tx_stats.bt_prio++; + break; + case AGG_TX_STATE_FEW_BYTES_MSK: + priv->reply_agg_tx_stats.few_bytes++; + break; + case AGG_TX_STATE_ABORT_MSK: + priv->reply_agg_tx_stats.abort++; + break; + case AGG_TX_STATE_LAST_SENT_TTL_MSK: + priv->reply_agg_tx_stats.last_sent_ttl++; + break; + case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: + priv->reply_agg_tx_stats.last_sent_try++; + break; + case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: + priv->reply_agg_tx_stats.last_sent_bt_kill++; + break; + case AGG_TX_STATE_SCD_QUERY_MSK: + priv->reply_agg_tx_stats.scd_query++; + break; + case AGG_TX_STATE_TEST_BAD_CRC32_MSK: + priv->reply_agg_tx_stats.bad_crc32++; + break; + case AGG_TX_STATE_RESPONSE_MSK: + priv->reply_agg_tx_stats.response++; + break; + case AGG_TX_STATE_DUMP_TX_MSK: + priv->reply_agg_tx_stats.dump_tx++; + break; + case AGG_TX_STATE_DELAY_TX_MSK: + priv->reply_agg_tx_stats.delay_tx++; + break; + default: + priv->reply_agg_tx_stats.unknown++; + break; + } +} + +static void iwlagn_set_tx_status(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + struct iwl_rxon_context *ctx, + struct iwlagn_tx_resp *tx_resp, + int txq_id, bool is_agg) +{ + u16 status = le16_to_cpu(tx_resp->status.status); + + info->status.rates[0].count = tx_resp->failure_frame + 1; + if (is_agg) + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->flags |= iwl_tx_status_to_mac80211(status); + iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), + info); + if (!iwl_is_tx_success(status)) + iwlagn_count_tx_err_status(priv, status); + + if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && + iwl_is_associated_ctx(ctx) && ctx->vif && + ctx->vif->type == NL80211_IFTYPE_STATION) { + ctx->last_tx_rejected = true; + iwl_stop_queue(priv, &priv->txq[txq_id]); + } + + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " + "0x%x retries %d\n", + txq_id, + iwl_get_tx_fail_reason(status), status, + le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x + +const char *iwl_get_agg_tx_fail_reason(u16 status) +{ + status &= AGG_TX_STATUS_MSK; + switch (status) { + case AGG_TX_STATE_TRANSMITTED: + return "SUCCESS"; + AGG_TX_STATE_FAIL(UNDERRUN_MSK); + AGG_TX_STATE_FAIL(BT_PRIO_MSK); + AGG_TX_STATE_FAIL(FEW_BYTES_MSK); + AGG_TX_STATE_FAIL(ABORT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); + AGG_TX_STATE_FAIL(SCD_QUERY_MSK); + AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); + AGG_TX_STATE_FAIL(RESPONSE_MSK); + AGG_TX_STATE_FAIL(DUMP_TX_MSK); + AGG_TX_STATE_FAIL(DELAY_TX_MSK); + } + + return "UNKNOWN"; +} +#endif /* CONFIG_IWLWIFI_DEBUG */ + +static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwlagn_tx_resp *tx_resp, + int txq_id, u16 start_idx) +{ + u16 status; + struct agg_tx_status *frame_status = &tx_resp->status; + struct ieee80211_hdr *hdr = NULL; + int i, sh, idx; + u16 seq; + + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); + + agg->frame_count = tx_resp->frame_count; + agg->start_idx = start_idx; + agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + agg->bitmap = 0; + + /* # frames attempted by Tx command */ + if (agg->frame_count == 1) { + struct iwl_tx_info *txb; + + /* Only one frame was attempted; no block-ack will arrive */ + idx = start_idx; + + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", + agg->frame_count, agg->start_idx, idx); + txb = &priv->txq[txq_id].txb[idx]; + iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), + txb->ctx, tx_resp, txq_id, true); + agg->wait_for_ba = 0; + } else { + /* Two or more frames were attempted; expect block-ack */ + u64 bitmap = 0; + + /* + * Start is the lowest frame sent. It may not be the first + * frame in the batch; we figure this out dynamically during + * the following loop. + */ + int start = agg->start_idx; + + /* Construct bit-map of pending frames within Tx window */ + for (i = 0; i < agg->frame_count; i++) { + u16 sc; + status = le16_to_cpu(frame_status[i].status); + seq = le16_to_cpu(frame_status[i].sequence); + idx = SEQ_TO_INDEX(seq); + txq_id = SEQ_TO_QUEUE(seq); + + if (status & AGG_TX_STATUS_MSK) + iwlagn_count_agg_tx_err_status(priv, status); + + if (status & (AGG_TX_STATE_FEW_BYTES_MSK | + AGG_TX_STATE_ABORT_MSK)) + continue; + + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", + agg->frame_count, txq_id, idx); + IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " + "try-count (0x%08x)\n", + iwl_get_agg_tx_fail_reason(status), + status & AGG_TX_STATUS_MSK, + status & AGG_TX_TRY_MSK); + + hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); + if (!hdr) { + IWL_ERR(priv, + "BUG_ON idx doesn't point to valid skb" + " idx=%d, txq_id=%d\n", idx, txq_id); + return -1; + } + + sc = le16_to_cpu(hdr->seq_ctrl); + if (idx != (SEQ_TO_SN(sc) & 0xff)) { + IWL_ERR(priv, + "BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", + idx, SEQ_TO_SN(sc), + hdr->seq_ctrl); + return -1; + } + + IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", + i, idx, SEQ_TO_SN(sc)); + + /* + * sh -> how many frames ahead of the starting frame is + * the current one? + * + * Note that all frames sent in the batch must be in a + * 64-frame window, so this number should be in [0,63]. + * If outside of this window, then we've found a new + * "first" frame in the batch and need to change start. + */ + sh = idx - start; + + /* + * If >= 64, out of window. start must be at the front + * of the circular buffer, idx must be near the end of + * the buffer, and idx is the new "first" frame. Shift + * the indices around. + */ + if (sh >= 64) { + /* Shift bitmap by start - idx, wrapped */ + sh = 0x100 - idx + start; + bitmap = bitmap << sh; + /* Now idx is the new start so sh = 0 */ + sh = 0; + start = idx; + /* + * If <= -64 then wraps the 256-pkt circular buffer + * (e.g., start = 255 and idx = 0, sh should be 1) + */ + } else if (sh <= -64) { + sh = 0x100 - start + idx; + /* + * If < 0 but > -64, out of window. idx is before start + * but not wrapped. Shift the indices around. + */ + } else if (sh < 0) { + /* Shift by how far start is ahead of idx */ + sh = start - idx; + bitmap = bitmap << sh; + /* Now idx is the new start so sh = 0 */ + start = idx; + sh = 0; + } + /* Sequence number start + sh was sent in this batch */ + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); + } + + /* + * Store the bitmap and possibly the new start, if we wrapped + * the buffer above + */ + agg->bitmap = bitmap; + agg->start_idx = start; + IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", + agg->frame_count, agg->start_idx, + (unsigned long long)agg->bitmap); + + if (bitmap) + agg->wait_for_ba = 1; + } + return 0; +} + +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status) +{ + if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { + IWL_ERR(priv, "Tx flush command to flush out all frames\n"); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + queue_work(priv->workqueue, &priv->tx_flush); + } +} + +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int index = SEQ_TO_INDEX(sequence); + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct ieee80211_tx_info *info; + struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct ieee80211_hdr *hdr; + struct iwl_tx_info *txb; + u32 status = le16_to_cpu(tx_resp->status.status); + int tid; + int sta_id; + int freed; + unsigned long flags; + + if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { + IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) " + "index %d is out of range [0-%d] %d %d\n", __func__, + txq_id, index, txq->q.n_bd, txq->q.write_ptr, + txq->q.read_ptr); + return; + } + + txq->time_stamp = jiffies; + txb = &txq->txb[txq->q.read_ptr]; + info = IEEE80211_SKB_CB(txb->skb); + memset(&info->status, 0, sizeof(info->status)); + + tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> + IWLAGN_TX_RES_TID_POS; + sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> + IWLAGN_TX_RES_RA_POS; + + spin_lock_irqsave(&priv->sta_lock, flags); + + hdr = (void *)txb->skb->data; + if (!ieee80211_is_data_qos(hdr->frame_control)) + priv->last_seq_ctl = tx_resp->seq_ctl; + + if (txq->sched_retry) { + const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); + struct iwl_ht_agg *agg; + + agg = &priv->stations[sta_id].tid[tid].agg; + /* + * If the BT kill count is non-zero, we'll get this + * notification again. + */ + if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && + priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n"); + } + iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); + + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + + if (txq->q.read_ptr != (scd_ssn & 0xff)) { + index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); + IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " + "scd_ssn=%d idx=%d txq=%d swq=%d\n", + scd_ssn , index, txq_id, txq->swq_id); + + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + (iwl_queue_space(&txq->q) > txq->q.low_mark) && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); + } + } else { + iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, + txq_id, false); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + iwl_queue_space(&txq->q) > txq->q.low_mark && + status != TX_STATUS_FAIL_PASSIVE_NO_RX) + iwl_wake_queue(priv, txq); + } + + iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); + + iwl_check_abort_status(priv, tx_resp->frame_count, status); + spin_unlock_irqrestore(&priv->sta_lock, flags); +} int iwlagn_hw_valid_rtc_data_addr(u32 addr) { @@ -53,7 +495,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; - if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status), + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), "TX Power requested while scanning!\n")) return -EAGAIN; @@ -83,7 +525,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -167,9 +609,6 @@ struct iwl_mod_params iwlagn_mod_params = { .bt_coex_active = true, .no_sleep_autoadjust = true, .power_level = IWL_POWER_INDEX_1, - .bt_ch_announce = true, - .wanted_ucode_alternative = 1, - .auto_agg = true, /* the rest are 0 by default */ }; @@ -328,15 +767,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u16 rx_chain = 0; enum ieee80211_band band; u8 n_probes = 0; - u8 rx_ant = hw_params(priv).valid_rx_ant; + u8 rx_ant = priv->hw_params.valid_rx_ant; u8 rate; bool is_active = false; int chan_mod; u8 active_chains; - u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; + u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (vif) ctx = iwl_rxon_ctx_from_vif(vif); @@ -503,7 +942,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); /* In power save mode use one chain, otherwise use all chains */ - if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->status)) { /* rx_ant has been set to all valid chains previously */ active_chains = rx_ant & ((u8)(priv->chain_noise_data.active_chains)); @@ -523,8 +962,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) } /* MIMO is not used here, but value is required */ - rx_chain |= - hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; + rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; @@ -606,15 +1044,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ - set_bit(STATUS_SCAN_HW, &priv->shrd->status); + set_bit(STATUS_SCAN_HW, &priv->status); ret = iwlagn_set_pan_params(priv); if (ret) return ret; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) { - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->status); iwlagn_set_pan_params(priv); } @@ -634,6 +1072,52 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, vif->bss_conf.bssid); } +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed) +{ + lockdep_assert_held(&priv->sta_lock); + + if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + else { + IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", + priv->stations[sta_id].tid[tid].tfds_in_queue, + freed); + priv->stations[sta_id].tid[tid].tfds_in_queue = 0; + } +} + +#define IWL_FLUSH_WAIT_MS 2000 + +int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) +{ + struct iwl_tx_queue *txq; + struct iwl_queue *q; + int cnt; + unsigned long now = jiffies; + int ret = 0; + + /* waiting for all the tx frames complete might take a while */ + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + if (cnt == priv->cmd_queue) + continue; + txq = &priv->txq[cnt]; + q = &txq->q; + while (q->read_ptr != q->write_ptr && !time_after(jiffies, + now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) + msleep(1); + + if (q->read_ptr != q->write_ptr) { + IWL_ERR(priv, "fail to flush all tx fifo queues\n"); + ret = -ETIMEDOUT; + break; + } + } + return ret; +} + +#define IWL_TX_QUEUE_MSK 0xfffff + /** * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode * @@ -659,7 +1143,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK; if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && - (priv->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS))) + (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | @@ -672,22 +1156,22 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ieee80211_stop_queues(priv->hw); if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { IWL_ERR(priv, "flush request fail\n"); goto done; } IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); - iwl_trans_wait_tx_queue_empty(trans(priv)); + iwlagn_wait_tx_queue_empty(priv); done: ieee80211_wake_queues(priv->hw); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -866,12 +1350,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (priv->cfg->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) @@ -884,7 +1368,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) struct iwl_rxon_context *ctx, *found_ctx = NULL; bool found_ap = false; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Check whether AP or GO mode is active. */ if (rssi_ena) { @@ -997,7 +1481,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * We can not send command to firmware while scanning. When the scan @@ -1006,7 +1490,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) * STATUS_SCANNING to avoid race when queue_work two times from * different notifications, but quit and not perform any work at all. */ - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (test_bit(STATUS_SCAN_HW, &priv->status)) goto out; iwl_update_chain_flags(priv); @@ -1025,7 +1509,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) */ iwlagn_bt_coex_rssi_monitor(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -1132,7 +1616,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; /* schedule to send runtime bt_config */ - queue_work(priv->shrd->workqueue, &priv->bt_runtime_config); + queue_work(priv->workqueue, &priv->bt_runtime_config); } } @@ -1176,7 +1660,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = coex->bt_status; - queue_work(priv->shrd->workqueue, + queue_work(priv->workqueue, &priv->bt_traffic_change_work); } } @@ -1185,9 +1669,9 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, /* FIXME: based on notification, adjust the prio_boost */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) @@ -1287,7 +1771,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; u32 active_chains; u16 rx_chain; @@ -1299,7 +1783,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (priv->chain_noise_data.active_chains) active_chains = priv->chain_noise_data.active_chains; else - active_chains = hw_params(priv).valid_rx_ant; + active_chains = priv->hw_params.valid_rx_ant; if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && @@ -1364,6 +1848,136 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) return ant; } +static const char *get_csr_string(int cmd) +{ + switch (cmd) { + IWL_CMD(CSR_HW_IF_CONFIG_REG); + IWL_CMD(CSR_INT_COALESCING); + IWL_CMD(CSR_INT); + IWL_CMD(CSR_INT_MASK); + IWL_CMD(CSR_FH_INT_STATUS); + IWL_CMD(CSR_GPIO_IN); + IWL_CMD(CSR_RESET); + IWL_CMD(CSR_GP_CNTRL); + IWL_CMD(CSR_HW_REV); + IWL_CMD(CSR_EEPROM_REG); + IWL_CMD(CSR_EEPROM_GP); + IWL_CMD(CSR_OTP_GP_REG); + IWL_CMD(CSR_GIO_REG); + IWL_CMD(CSR_GP_UCODE_REG); + IWL_CMD(CSR_GP_DRIVER_REG); + IWL_CMD(CSR_UCODE_DRV_GP1); + IWL_CMD(CSR_UCODE_DRV_GP2); + IWL_CMD(CSR_LED_REG); + IWL_CMD(CSR_DRAM_INT_TBL_REG); + IWL_CMD(CSR_GIO_CHICKEN_BITS); + IWL_CMD(CSR_ANA_PLL_CFG); + IWL_CMD(CSR_HW_REV_WA_REG); + IWL_CMD(CSR_DBG_HPET_MEM_REG); + default: + return "UNKNOWN"; + } +} + +void iwl_dump_csr(struct iwl_priv *priv) +{ + int i; + static const u32 csr_tbl[] = { + CSR_HW_IF_CONFIG_REG, + CSR_INT_COALESCING, + CSR_INT, + CSR_INT_MASK, + CSR_FH_INT_STATUS, + CSR_GPIO_IN, + CSR_RESET, + CSR_GP_CNTRL, + CSR_HW_REV, + CSR_EEPROM_REG, + CSR_EEPROM_GP, + CSR_OTP_GP_REG, + CSR_GIO_REG, + CSR_GP_UCODE_REG, + CSR_GP_DRIVER_REG, + CSR_UCODE_DRV_GP1, + CSR_UCODE_DRV_GP2, + CSR_LED_REG, + CSR_DRAM_INT_TBL_REG, + CSR_GIO_CHICKEN_BITS, + CSR_ANA_PLL_CFG, + CSR_HW_REV_WA_REG, + CSR_DBG_HPET_MEM_REG + }; + IWL_ERR(priv, "CSR values:\n"); + IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " + "CSR_INT_PERIODIC_REG)\n"); + for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { + IWL_ERR(priv, " %25s: 0X%08x\n", + get_csr_string(csr_tbl[i]), + iwl_read32(priv, csr_tbl[i])); + } +} + +static const char *get_fh_string(int cmd) +{ + switch (cmd) { + IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); + IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); + IWL_CMD(FH_RSCSR_CHNL0_WPTR); + IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); + IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); + IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); + IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); + IWL_CMD(FH_TSSR_TX_STATUS_REG); + IWL_CMD(FH_TSSR_TX_ERROR_REG); + default: + return "UNKNOWN"; + } +} + +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) +{ + int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif + static const u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, + FH_RSCSR_CHNL0_WPTR, + FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_MEM_RSSR_SHARED_CTRL_REG, + FH_MEM_RSSR_RX_STATUS_REG, + FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return pos; + } +#endif + IWL_ERR(priv, "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + IWL_ERR(priv, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return 0; +} + /* notification wait support */ void iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ffee15ba06a8..1fa438e20f0a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -297,10 +297,10 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, u8 *qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } else - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; if (unlikely(tid >= TID_MAX_LOAD_COUNT)) - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; tl = &lq_data->load[tid]; @@ -313,7 +313,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, tl->queue_count = 1; tl->head = 0; tl->packet_count[0] = 1; - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; } time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); @@ -420,7 +420,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, load = rs_tl_get_load(lq_data, tid); - if ((iwlagn_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { + if (load > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); ret = ieee80211_start_tx_ba_session(sta, tid, 5000); @@ -819,7 +819,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, if (num_of_ant(tbl->ant_type) > 1) tbl->ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); tbl->is_ht40 = 0; tbl->is_SGI = 0; @@ -877,12 +877,12 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, * Is there a need to switch between * full concurrency and 3-wire? */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) full_concurrent = true; else full_concurrent = false; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { @@ -893,7 +893,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); - queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency); + queue_work(priv->workqueue, &priv->bt_full_concurrency); } } @@ -1293,7 +1293,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (hw_params(priv).tx_chains_num < 2) + if (priv->hw_params.tx_chains_num < 2) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); @@ -1349,7 +1349,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (hw_params(priv).tx_chains_num < 3) + if (priv->hw_params.tx_chains_num < 3) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); @@ -1448,8 +1448,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret = 0; u8 update_search_tbl_counter = 0; @@ -1459,16 +1459,14 @@ static int rs_move_legacy_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && tbl->action != IWL_LEGACY_SWITCH_SISO) tbl->action = IWL_LEGACY_SWITCH_SISO; @@ -1491,8 +1489,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_SISO; - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); } start_action = tbl->action; @@ -1626,8 +1623,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1637,16 +1634,14 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; @@ -1663,8 +1658,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, /* configure as 1x1 if bt full concurrency */ if (priv->bt_full_concurrent) { - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; } @@ -1800,8 +1794,8 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1970,8 +1964,8 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret; u8 update_search_tbl_counter = 0; @@ -2214,6 +2208,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) /* * setup rate table in uCode + * return rate_n_flags as used in the table */ static void rs_update_rate_tbl(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -2260,7 +2255,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 done_search = 0; u16 high_low; s32 sr; - u8 tid = IWL_MAX_TID_COUNT; + u8 tid = MAX_TID_COUNT; struct iwl_tid_data *tid_data; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_rxon_context *ctx = sta_priv->common.ctx; @@ -2279,9 +2274,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); - if ((tid != IWL_MAX_TID_COUNT) && - (lq_sta->tx_agg_tid_en & (1 << tid))) { - tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid]; + if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { + tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; if (tid_data->agg.state == IWL_AGG_OFF) lq_sta->is_agg = 0; else @@ -2651,10 +2645,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, iwl_ht_enabled(priv)) { if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && - (tid != IWL_MAX_TID_COUNT)) { - u8 sta_id = lq_sta->lq.sta_id; + (tid != MAX_TID_COUNT)) { tid_data = - &priv->shrd->tid_data[sta_id][tid]; + &priv->stations[lq_sta->lq.sta_id].tid[tid]; if (tid_data->agg.state == IWL_AGG_OFF) { IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", @@ -2710,7 +2703,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = lq_sta->last_txrate_idx; - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; if (!lq_sta->search_better_tbl) active_tbl = lq_sta->active_tbl; @@ -2893,15 +2886,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i /* These values will be overridden later */ lq_sta->lq.general_params.single_stream_ant_msk = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); lq_sta->lq.general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant & - ~first_antenna(hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); if (!lq_sta->lq.general_params.dual_stream_ant_msk) { lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { lq_sta->lq.general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant; + priv->hw_params.valid_tx_ant; } /* as default allow aggregation for all tids */ @@ -2947,7 +2940,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); } /* How many times should we repeat the initial rate? */ @@ -2979,7 +2972,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv->bt_full_concurrent) valid_tx_ant = ANT_A; else - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; } /* Fill rest of rate table */ @@ -3013,7 +3006,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); } /* Indicate to uCode which entries might be MIMO. @@ -3104,7 +3097,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, u8 ant_sel_tx; priv = lq_sta->drv; - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; if (lq_sta->dbg_fixed_rate) { ant_sel_tx = ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) @@ -3175,9 +3168,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, desc += sprintf(buff+desc, "fixed rate 0x%X\n", lq_sta->dbg_fixed_rate); desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", - (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "", - (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "", - (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : ""); + (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", + (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", + (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); desc += sprintf(buff+desc, "lq type %s\n", (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); if (is_Ht(tbl->lq_type)) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 00e6fc59e459..d562e9359d97 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -31,7 +31,6 @@ #include "iwl-agn-calib.h" #include "iwl-helpers.h" #include "iwl-trans.h" -#include "iwl-shared.h" static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -41,7 +40,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -67,7 +66,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -93,7 +92,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -122,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -132,7 +131,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv, struct ieee80211_vif *vif) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); @@ -181,7 +180,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -267,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -311,12 +310,12 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) int slot0 = 300, slot1 = 0; int ret; - if (priv->shrd->valid_contexts == BIT(IWL_RXON_CTX_BSS)) + if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) return 0; BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; @@ -363,7 +362,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot0 = bcnint / 2; slot1 = bcnint - slot0; - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) || + if (test_bit(STATUS_SCAN_HW, &priv->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; @@ -379,7 +378,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) ctx_pan->beacon_int; slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; slot1 = IWL_MIN_SLOT_TIME; } @@ -388,7 +387,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[1].width = cpu_to_le16(slot1); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); @@ -421,12 +420,12 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EBUSY; /* This function hardcodes a bunch of dual-mode assumptions */ @@ -435,10 +434,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (!ctx->is_active) return 0; - /* override BSSID if necessary due to preauth */ - if (ctx->preauth_bssid) - memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN); - /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; @@ -456,7 +451,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) else ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - iwl_print_rx_config_cmd(priv, ctx->ctxid); + iwl_print_rx_config_cmd(priv, ctx); ret = iwl_check_rxon_cmd(priv, ctx); if (ret) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); @@ -467,7 +462,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) && + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_channel)); @@ -541,14 +536,14 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "changed %#x", changed); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); goto out; } - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; } @@ -580,7 +575,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); for_each_context(priv, ctx) { /* Configure HT40 channels */ @@ -624,7 +619,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->vif); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); iwl_update_bcast_stations(priv); @@ -656,7 +651,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) iwlagn_commit_rxon(priv, ctx); } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -671,7 +666,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap; bool need_multiple; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -775,7 +770,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, priv->phy_calib_chain_noise_reset_cmd); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -796,17 +791,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, int ret; bool force = false; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (unlikely(!iwl_is_ready(priv->shrd))) { + if (unlikely(!iwl_is_ready(priv))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } if (unlikely(!ctx->vif)) { IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } @@ -839,8 +834,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, */ if (ctx->last_tx_rejected) { ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), - ctx->ctxid); + iwl_wake_any_queue(priv, ctx); } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -901,7 +895,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, if (!priv->disable_chain_noise_cal) iwlagn_chain_noise_reset(priv); priv->start_calib = 1; - WARN_ON(ctx->preauth_bssid); } if (changes & BSS_CHANGED_IBSS) { @@ -919,7 +912,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, IWL_ERR(priv, "Error sending IBSS beacon\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwlagn_post_scan(struct iwl_priv *priv) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 8f0b86de1863..37e624095e40 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -49,7 +49,7 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) return NULL; } - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ @@ -63,23 +63,23 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) rate_flags |= RATE_MCS_CCK_MSK; - rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) << + rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << RATE_MCS_ANT_POS; rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) link_cmd->rs_table[i].rate_n_flags = rate_n_flags; link_cmd->general_params.single_stream_ant_msk = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); link_cmd->general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant & - ~first_antenna(hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); if (!link_cmd->general_params.dual_stream_ant_msk) { link_cmd->general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { link_cmd->general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant; + priv->hw_params.valid_tx_ant; } link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; @@ -116,9 +116,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (sta_id_r) *sta_id_r = sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_LOCAL; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); /* Set up default rate scaling table in device's station table */ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); @@ -132,9 +132,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (ret) IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -189,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); else return 0; } @@ -197,7 +197,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); return iwl_send_static_wepkey_cmd(priv, ctx, false); } @@ -208,13 +208,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return 0; @@ -232,7 +232,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { @@ -311,9 +311,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv, struct iwl_addsta_cmd sta_cmd; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags |= STA_KEY_FLG_MAP_KEY_MSK; @@ -388,16 +388,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -ENOENT; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) sta_id = IWL_INVALID_STATION; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); if (sta_id == IWL_INVALID_STATION) return 0; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx->key_mapping_keys--; @@ -430,7 +430,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -EINVAL; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) @@ -493,18 +493,18 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, unsigned long flags; u8 sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare broadcast station\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; } priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_BCAST; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); if (!link_cmd) { @@ -513,9 +513,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -539,13 +539,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (priv->stations[sta_id].lq) kfree(priv->stations[sta_id].lq); else IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -572,15 +572,15 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) unsigned long flags; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -592,20 +592,20 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) return -ENXIO; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -617,7 +617,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { @@ -625,13 +625,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return -ENXIO; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -640,14 +640,14 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = 0; priv->stations[sta_id].sta.sleep_tx_count = 0; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } @@ -655,7 +655,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) { unsigned long flags; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = @@ -663,7 +663,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 92ba8cd0ecd5..f501d742984c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -176,24 +176,24 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) struct iwl_tt_mgmt *tt = &priv->thermal_throttle; unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (tt->state == IWL_TI_CT_KILL) { if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; } else { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = true; } - iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - if (!iwl_grab_nic_access(bus(priv))) - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); /* Reschedule the ct_kill timer to occur in * CT_KILL_EXIT_DURATION seconds to ensure we get a @@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, { if (stop) { IWL_DEBUG_TEMP(priv, "Stop all queues\n"); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); IWL_DEBUG_TEMP(priv, "Schedule 5 seconds CT_KILL Timer\n"); @@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, jiffies + CT_KILL_EXIT_DURATION * HZ); } else { IWL_DEBUG_TEMP(priv, "Wake all queues\n"); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_wake_queues(priv->hw); } } @@ -227,7 +227,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) struct iwl_priv *priv = (struct iwl_priv *)data; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* temperature timer expired, ready to go into CT_KILL state */ @@ -235,7 +235,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) IWL_DEBUG_TEMP(priv, "entering CT_KILL state when " "temperature timer expired\n"); tt->state = IWL_TI_CT_KILL; - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } } @@ -313,24 +313,23 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) tt->tt_power_mode = IWL_POWER_INDEX_5; break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated * try again during next temperature read */ if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); } else { if (tt->state == IWL_TI_CT_KILL) { if (force) { - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -344,7 +343,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", tt->tt_power_mode); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } @@ -454,9 +453,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) * in case get disabled before */ iwl_set_rxon_ht(priv, &priv->current_ht_config); } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated @@ -465,7 +464,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; } else { IWL_DEBUG_TEMP(priv, @@ -476,8 +475,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) if (force) { IWL_DEBUG_TEMP(priv, "Enter IWL_TI_CT_KILL\n"); - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -489,7 +487,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) iwl_perform_ct_kill_task(priv, false); } } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } @@ -508,10 +506,10 @@ static void iwl_bg_ct_enter(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; if (tt->state != IWL_TI_CT_KILL) { @@ -537,10 +535,10 @@ static void iwl_bg_ct_exit(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; /* stop ct_kill_exit_tm timer */ @@ -567,20 +565,20 @@ static void iwl_bg_ct_exit(struct work_struct *work) void iwl_tt_enter_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); - queue_work(priv->shrd->workqueue, &priv->ct_enter); + queue_work(priv->workqueue, &priv->ct_enter); } void iwl_tt_exit_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); - queue_work(priv->shrd->workqueue, &priv->ct_exit); + queue_work(priv->workqueue, &priv->ct_exit); } static void iwl_bg_tt_work(struct work_struct *work) @@ -588,7 +586,7 @@ static void iwl_bg_tt_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->cfg->base_params->temperature_kelvin) @@ -602,11 +600,11 @@ static void iwl_bg_tt_work(struct work_struct *work) void iwl_tt_handler(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); - queue_work(priv->shrd->workqueue, &priv->tt_work); + queue_work(priv->workqueue, &priv->tt_work); } /* Thermal throttling initialization diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h index 7282a23e8f1c..d118ed29bf3f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -117,6 +117,7 @@ struct iwl_tt_mgmt { u8 iwl_tt_current_power_mode(struct iwl_priv *priv); bool iwl_tt_is_low_power_state(struct iwl_priv *priv); bool iwl_ht_enabled(struct iwl_priv *priv); +bool iwl_check_for_ct_kill(struct iwl_priv *priv); enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); void iwl_tt_enter_ct_kill(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ba5c514c4a43..9bc26da62768 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "iwl-dev.h" #include "iwl-core.h" @@ -42,6 +41,79 @@ #include "iwl-agn.h" #include "iwl-trans.h" +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific modules like + * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity + * mapping. + */ + +static const u8 tid_to_ac[] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO +}; + +static inline int get_ac_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return tid_to_ac[tid]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + +static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return ctx->ac_to_fifo[tid_to_ac[tid]]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, + int tid) +{ + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues - 1); + return -EINVAL; + } + + /* Modify device's station table to Tx this TID */ + return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); +} + static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) @@ -188,10 +260,10 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, priv->bt_full_concurrent) { /* operated as 1x1 in full concurrency mode */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - first_antenna(hw_params(priv).valid_tx_ant)); + first_antenna(priv->hw_params.valid_tx_ant)); } else priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant); rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* Set the rate in the TX cmd */ @@ -249,21 +321,23 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_station_priv *sta_priv = NULL; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl_device_cmd *dev_cmd = NULL; struct iwl_tx_cmd *tx_cmd; + int txq_id; + u16 seq_number = 0; __le16 fc; u8 hdr_len; u16 len; u8 sta_id; + u8 tid = 0; unsigned long flags; bool is_agg = false; if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); - spin_lock_irqsave(&priv->shrd->lock, flags); - if (iwl_is_rfkill(priv->shrd)) { + spin_lock_irqsave(&priv->lock, flags); + if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; } @@ -313,16 +387,51 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - /* irqs already disabled/saved above when locking priv->shrd->lock */ - spin_lock(&priv->shrd->sta_lock); + /* + * Send this frame after DTIM -- there's a special queue + * reserved for this for contexts that support AP mode. + */ + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + txq_id = ctx->mcast_queue; + /* + * The microcode will clear the more data + * bit in the last frame it transmits. + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) + txq_id = IWL_AUX_QUEUE; + else + txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; - dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); + /* irqs already disabled/saved above when locking priv->lock */ + spin_lock(&priv->sta_lock); - if (unlikely(!dev_cmd)) - goto drop_unlock_sta; + if (ieee80211_is_data_qos(fc)) { + u8 *qc = NULL; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + + if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) + goto drop_unlock_sta; + + seq_number = priv->stations[sta_id].tid[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number += 0x10; + /* aggregation is on for this */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { + txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + is_agg = true; + } + } - memset(dev_cmd, 0, sizeof(*dev_cmd)); - tx_cmd = &dev_cmd->cmd.tx; + tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id); + if (unlikely(!tx_cmd)) + goto drop_unlock_sta; /* Copy MAC header from skb into command buffer */ memcpy(tx_cmd->hdr, hdr, hdr_len); @@ -342,14 +451,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - info->driver_data[0] = ctx; - info->driver_data[1] = dev_cmd; - - if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id)) + if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx)) goto drop_unlock_sta; - spin_unlock(&priv->shrd->sta_lock); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + if (ieee80211_is_data_qos(fc)) { + priv->stations[sta_id].tid[tid].tfds_in_queue++; + if (!ieee80211_has_morefrags(fc)) + priv->stations[sta_id].tid[tid].seq_number = seq_number; + } + + spin_unlock(&priv->sta_lock); + spin_unlock_irqrestore(&priv->lock, flags); /* * Avoid atomic ops if it isn't an associated client. @@ -364,20 +476,41 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) return 0; drop_unlock_sta: - if (dev_cmd) - kmem_cache_free(priv->tx_cmd_pool, dev_cmd); - spin_unlock(&priv->shrd->sta_lock); + spin_unlock(&priv->sta_lock); drop_unlock_priv: - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); + return -1; +} + +/* + * Find first available (lowest unused) Tx Queue, mark it "active". + * Called only when finding queue for aggregation. + * Should never return anything < 7, because they should already + * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) + */ +static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) +{ + int txq_id; + + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) + return txq_id; return -1; } int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int sta_id; + int tx_fifo; + int txq_id; int ret; + unsigned long flags; + struct iwl_tid_data *tid_data; + + tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); + if (unlikely(tx_fifo < 0)) + return tx_fifo; IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", sta->addr, tid); @@ -387,29 +520,58 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; } - if (unlikely(tid >= IWL_MAX_TID_COUNT)) + if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) { + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); return -ENXIO; } - ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); + txq_id = iwlagn_txq_ctx_activate_free(priv); + if (txq_id == -1) { + IWL_ERR(priv, "No free aggregation queue available\n"); + return -ENXIO; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.txq_id = txq_id; + tid_data->agg.tx_fifo = tx_fifo; + iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); if (ret) return ret; - ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id, - tid, ssn); - + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(priv, "HW queue is empty\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + } else { + IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", + tid_data->tfds_in_queue); + tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; + } + spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - int sta_id; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + int tx_fifo_id, txq_id, sta_id, ssn; + struct iwl_tid_data *tid_data; + int write_ptr, read_ptr; + unsigned long flags; + + tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); + if (unlikely(tx_fifo_id < 0)) + return tx_fifo_id; sta_id = iwl_sta_id(sta); @@ -418,8 +580,101 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid, - sta_id, tid); + spin_lock_irqsave(&priv->sta_lock, flags); + + tid_data = &priv->stations[sta_id].tid[tid]; + ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + txq_id = tid_data->agg.txq_id; + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* + * This can happen if the peer stops aggregation + * again before we've had a chance to drain the + * queue we selected previously, i.e. before the + * session was really started completely. + */ + IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); + goto turn_off; + case IWL_AGG_ON: + break; + default: + IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); + } + + write_ptr = priv->txq[txq_id].q.write_ptr; + read_ptr = priv->txq[txq_id].q.read_ptr; + + /* The queue is not empty */ + if (write_ptr != read_ptr) { + IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); + priv->stations[sta_id].tid[tid].agg.state = + IWL_EMPTYING_HW_QUEUE_DELBA; + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } + + IWL_DEBUG_HT(priv, "HW queue is empty\n"); + turn_off: + priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + + /* do not restore/save irqs */ + spin_unlock(&priv->sta_lock); + spin_lock(&priv->lock); + + /* + * the only reason this call can fail is queue number out of range, + * which can happen if uCode is reloaded and all the station + * information are lost. if it is outside the range, there is no need + * to deactivate the uCode queue, just return "success" to allow + * mac80211 to clean up it own data. + */ + trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); + spin_unlock_irqrestore(&priv->lock, flags); + + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + + return 0; +} + +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id) +{ + struct iwl_queue *q = &priv->txq[txq_id].q; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + struct iwl_rxon_context *ctx; + + ctx = &priv->contexts[priv->stations[sta_id].ctxid]; + + lockdep_assert_held(&priv->sta_lock); + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_DELBA: + /* We are reclaiming the last packet of the */ + /* aggregated HW queue */ + if ((txq_id == tid_data->agg.txq_id) && + (q->read_ptr == q->write_ptr)) { + u16 ssn = SEQ_TO_SN(tid_data->seq_number); + int tx_fifo = get_fifo_from_tid(ctx, tid); + IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); + trans_txq_agg_disable(&priv->trans, txq_id, + ssn, tx_fifo); + tid_data->agg.state = IWL_AGG_OFF; + ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* We are reclaiming the last packet of the queue */ + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + } + break; + } + + return 0; } static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, @@ -441,389 +696,147 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, rcu_read_unlock(); } -/** - * translate ucode response to mac80211 tx status control values - */ -static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info) +static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info, + bool is_agg) { - struct ieee80211_tx_rate *r = &info->control.rates[0]; - - info->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) - r->flags |= IEEE80211_TX_RC_MCS; - if (rate_n_flags & RATE_MCS_GF_MSK) - r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_HT40_MSK) - r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) - r->flags |= IEEE80211_TX_RC_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) - r->flags |= IEEE80211_TX_RC_SHORT_GI; - r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -const char *iwl_get_tx_fail_reason(u32 status) -{ -#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x -#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x - - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_POSTPONE(DELAY); - TX_STATUS_POSTPONE(FEW_BYTES); - TX_STATUS_POSTPONE(BT_PRIO); - TX_STATUS_POSTPONE(QUIET_PERIOD); - TX_STATUS_POSTPONE(CALC_TTAK); - TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); - TX_STATUS_FAIL(SHORT_LIMIT); - TX_STATUS_FAIL(LONG_LIMIT); - TX_STATUS_FAIL(FIFO_UNDERRUN); - TX_STATUS_FAIL(DRAIN_FLOW); - TX_STATUS_FAIL(RFKILL_FLUSH); - TX_STATUS_FAIL(LIFE_EXPIRE); - TX_STATUS_FAIL(DEST_PS); - TX_STATUS_FAIL(HOST_ABORTED); - TX_STATUS_FAIL(BT_RETRY); - TX_STATUS_FAIL(STA_INVALID); - TX_STATUS_FAIL(FRAG_DROPPED); - TX_STATUS_FAIL(TID_DISABLE); - TX_STATUS_FAIL(FIFO_FLUSHED); - TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); - TX_STATUS_FAIL(PASSIVE_NO_RX); - TX_STATUS_FAIL(NO_BEACON_ON_RADAR); - } + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; - return "UNKNOWN"; + if (!is_agg) + iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1); -#undef TX_STATUS_FAIL -#undef TX_STATUS_POSTPONE + ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); } -#endif /* CONFIG_IWLWIFI_DEBUG */ -static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { - status &= AGG_TX_STATUS_MSK; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_tx_info *tx_info; + int nfreed = 0; + struct ieee80211_hdr *hdr; - switch (status) { - case AGG_TX_STATE_UNDERRUN_MSK: - priv->reply_agg_tx_stats.underrun++; - break; - case AGG_TX_STATE_BT_PRIO_MSK: - priv->reply_agg_tx_stats.bt_prio++; - break; - case AGG_TX_STATE_FEW_BYTES_MSK: - priv->reply_agg_tx_stats.few_bytes++; - break; - case AGG_TX_STATE_ABORT_MSK: - priv->reply_agg_tx_stats.abort++; - break; - case AGG_TX_STATE_LAST_SENT_TTL_MSK: - priv->reply_agg_tx_stats.last_sent_ttl++; - break; - case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: - priv->reply_agg_tx_stats.last_sent_try++; - break; - case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: - priv->reply_agg_tx_stats.last_sent_bt_kill++; - break; - case AGG_TX_STATE_SCD_QUERY_MSK: - priv->reply_agg_tx_stats.scd_query++; - break; - case AGG_TX_STATE_TEST_BAD_CRC32_MSK: - priv->reply_agg_tx_stats.bad_crc32++; - break; - case AGG_TX_STATE_RESPONSE_MSK: - priv->reply_agg_tx_stats.response++; - break; - case AGG_TX_STATE_DUMP_TX_MSK: - priv->reply_agg_tx_stats.dump_tx++; - break; - case AGG_TX_STATE_DELAY_TX_MSK: - priv->reply_agg_tx_stats.delay_tx++; - break; - default: - priv->reply_agg_tx_stats.unknown++; - break; + if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { + IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " + "index %d is out of range [0-%d] %d %d.\n", __func__, + txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); + return 0; } -} -static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, - struct iwlagn_tx_resp *tx_resp) -{ - struct agg_tx_status *frame_status = &tx_resp->status; - int tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> - IWLAGN_TX_RES_TID_POS; - int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> - IWLAGN_TX_RES_RA_POS; - struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg; - u32 status = le16_to_cpu(tx_resp->status.status); - int i; - - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, - "got tx response w/o block-ack\n"); + for (index = iwl_queue_inc_wrap(index, q->n_bd); + q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - agg->wait_for_ba = (tx_resp->frame_count > 1); + tx_info = &txq->txb[txq->q.read_ptr]; - /* - * If the BT kill count is non-zero, we'll get this - * notification again. - */ - if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { - IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); - } + if (WARN_ON_ONCE(tx_info->skb == NULL)) + continue; - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < tx_resp->frame_count; i++) { - u16 fstatus = le16_to_cpu(frame_status[i].status); + hdr = (struct ieee80211_hdr *)tx_info->skb->data; + if (ieee80211_is_data_qos(hdr->frame_control)) + nfreed++; - if (status & AGG_TX_STATUS_MSK) - iwlagn_count_agg_tx_err_status(priv, fstatus); + iwlagn_tx_status(priv, tx_info, + txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); + tx_info->skb = NULL; - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; + iwlagn_txq_inval_byte_cnt_tbl(priv, txq); - IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " - "try-count (0x%08x)\n", - iwl_get_agg_tx_fail_reason(fstatus), - fstatus & AGG_TX_STATUS_MSK, - fstatus & AGG_TX_TRY_MSK); + iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr); } + return nfreed; } -#ifdef CONFIG_IWLWIFI_DEBUG -#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x +/** + * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack + * + * Go through block-ack's bitmap of ACK'd frames, update driver's record of + * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. + */ +static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwl_compressed_ba_resp *ba_resp) -const char *iwl_get_agg_tx_fail_reason(u16 status) { - status &= AGG_TX_STATUS_MSK; - switch (status) { - case AGG_TX_STATE_TRANSMITTED: - return "SUCCESS"; - AGG_TX_STATE_FAIL(UNDERRUN_MSK); - AGG_TX_STATE_FAIL(BT_PRIO_MSK); - AGG_TX_STATE_FAIL(FEW_BYTES_MSK); - AGG_TX_STATE_FAIL(ABORT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); - AGG_TX_STATE_FAIL(SCD_QUERY_MSK); - AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); - AGG_TX_STATE_FAIL(RESPONSE_MSK); - AGG_TX_STATE_FAIL(DUMP_TX_MSK); - AGG_TX_STATE_FAIL(DELAY_TX_MSK); + int sh; + u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + struct ieee80211_tx_info *info; + u64 bitmap, sent_bitmap; + + if (unlikely(!agg->wait_for_ba)) { + if (unlikely(ba_resp->bitmap)) + IWL_ERR(priv, "Received BA when not expected\n"); + return -EINVAL; } - return "UNKNOWN"; -} -#endif /* CONFIG_IWLWIFI_DEBUG */ + /* Mark that the expected block-ack response arrived */ + agg->wait_for_ba = 0; + IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); -static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) -{ - return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & MAX_SN; -} + /* Calculate shift to align block-ack bits with our Tx window bits */ + sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); + if (sh < 0) + sh += 0x100; -static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) -{ - status &= TX_STATUS_MSK; + /* + * Check for success or failure according to the + * transmitted bitmap and block-ack bitmap + */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + sent_bitmap = bitmap & agg->bitmap; - switch (status) { - case TX_STATUS_POSTPONE_DELAY: - priv->reply_tx_stats.pp_delay++; - break; - case TX_STATUS_POSTPONE_FEW_BYTES: - priv->reply_tx_stats.pp_few_bytes++; - break; - case TX_STATUS_POSTPONE_BT_PRIO: - priv->reply_tx_stats.pp_bt_prio++; - break; - case TX_STATUS_POSTPONE_QUIET_PERIOD: - priv->reply_tx_stats.pp_quiet_period++; - break; - case TX_STATUS_POSTPONE_CALC_TTAK: - priv->reply_tx_stats.pp_calc_ttak++; - break; - case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: - priv->reply_tx_stats.int_crossed_retry++; - break; - case TX_STATUS_FAIL_SHORT_LIMIT: - priv->reply_tx_stats.short_limit++; - break; - case TX_STATUS_FAIL_LONG_LIMIT: - priv->reply_tx_stats.long_limit++; - break; - case TX_STATUS_FAIL_FIFO_UNDERRUN: - priv->reply_tx_stats.fifo_underrun++; - break; - case TX_STATUS_FAIL_DRAIN_FLOW: - priv->reply_tx_stats.drain_flow++; - break; - case TX_STATUS_FAIL_RFKILL_FLUSH: - priv->reply_tx_stats.rfkill_flush++; - break; - case TX_STATUS_FAIL_LIFE_EXPIRE: - priv->reply_tx_stats.life_expire++; - break; - case TX_STATUS_FAIL_DEST_PS: - priv->reply_tx_stats.dest_ps++; - break; - case TX_STATUS_FAIL_HOST_ABORTED: - priv->reply_tx_stats.host_abort++; - break; - case TX_STATUS_FAIL_BT_RETRY: - priv->reply_tx_stats.bt_retry++; - break; - case TX_STATUS_FAIL_STA_INVALID: - priv->reply_tx_stats.sta_invalid++; - break; - case TX_STATUS_FAIL_FRAG_DROPPED: - priv->reply_tx_stats.frag_drop++; - break; - case TX_STATUS_FAIL_TID_DISABLE: - priv->reply_tx_stats.tid_disable++; - break; - case TX_STATUS_FAIL_FIFO_FLUSHED: - priv->reply_tx_stats.fifo_flush++; - break; - case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: - priv->reply_tx_stats.insuff_cf_poll++; - break; - case TX_STATUS_FAIL_PASSIVE_NO_RX: - priv->reply_tx_stats.fail_hw_drop++; - break; - case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: - priv->reply_tx_stats.sta_color_mismatch++; - break; - default: - priv->reply_tx_stats.unknown++; - break; + /* Sanity check values reported by uCode */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + ba_resp->txed = ba_resp->txed_2_done; } -} - -static void iwlagn_set_tx_status(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwlagn_tx_resp *tx_resp, - bool is_agg) -{ - u16 status = le16_to_cpu(tx_resp->status.status); - - info->status.rates[0].count = tx_resp->failure_frame + 1; - if (is_agg) - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_tx_status_to_mac80211(status); - iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), - info); - if (!iwl_is_tx_success(status)) - iwlagn_count_tx_err_status(priv, status); -} + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); -static void iwl_check_abort_status(struct iwl_priv *priv, - u8 frame_count, u32 status) -{ - if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { - IWL_ERR(priv, "Tx flush command to flush out all frames\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - queue_work(priv->shrd->workqueue, &priv->tx_flush); + /* Find the first ACKed frame to store the TX status */ + while (sent_bitmap && !(sent_bitmap & 1)) { + agg->start_idx = (agg->start_idx + 1) & 0xff; + sent_bitmap >>= 1; } + + info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); + memset(&info->status, 0, sizeof(info->status)); + info->flags |= IEEE80211_TX_STAT_ACK; + info->flags |= IEEE80211_TX_STAT_AMPDU; + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; + iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + + return 0; } -void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +/** + * translate ucode response to mac80211 tx status control values + */ +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info) { - struct iwl_rx_packet *pkt = rxb_addr(rxb); - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence); - struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - struct ieee80211_hdr *hdr; - u32 status = le16_to_cpu(tx_resp->status.status); - u32 ssn = iwlagn_get_scd_ssn(tx_resp); - int tid; - int sta_id; - int freed; - struct ieee80211_tx_info *info; - unsigned long flags; - struct sk_buff_head skbs; - struct sk_buff *skb; - struct iwl_rxon_context *ctx; - bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); - - tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> - IWLAGN_TX_RES_TID_POS; - sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> - IWLAGN_TX_RES_RA_POS; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - - if (is_agg) - iwl_rx_reply_tx_agg(priv, tx_resp); - - if (tx_resp->frame_count == 1) { - __skb_queue_head_init(&skbs); - /*we can free until ssn % q.n_bd not inclusive */ - iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, - ssn, status, &skbs); - freed = 0; - while (!skb_queue_empty(&skbs)) { - skb = __skb_dequeue(&skbs); - hdr = (struct ieee80211_hdr *)skb->data; - - if (!ieee80211_is_data_qos(hdr->frame_control)) - priv->last_seq_ctl = tx_resp->seq_ctl; - - info = IEEE80211_SKB_CB(skb); - ctx = info->driver_data[0]; - kmem_cache_free(priv->tx_cmd_pool, - (info->driver_data[1])); - - memset(&info->status, 0, sizeof(info->status)); - - if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && - iwl_is_associated_ctx(ctx) && ctx->vif && - ctx->vif->type == NL80211_IFTYPE_STATION) { - ctx->last_tx_rejected = true; - iwl_trans_stop_queue(trans(priv), txq_id); - - IWL_DEBUG_TX_REPLY(priv, - "TXQ %d status %s (0x%08x) " - "rate_n_flags 0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), - status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY(priv, - "FrameCnt = %d, idx=%d\n", - tx_resp->frame_count, cmd_index); - } - - /* check if BAR is needed */ - if (is_agg && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), - tx_resp, is_agg); - if (!is_agg) - iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); - - ieee80211_tx_status_irqsafe(priv->hw, skb); - - freed++; - } - - WARN_ON(!is_agg && freed != 1); - } + struct ieee80211_tx_rate *r = &info->control.rates[0]; - iwl_check_abort_status(priv, tx_resp->frame_count, status); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + info->antenna_sel_tx = + ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); + if (rate_n_flags & RATE_MCS_HT_MSK) + r->flags |= IEEE80211_TX_RC_MCS; + if (rate_n_flags & RATE_MCS_GF_MSK) + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + if (rate_n_flags & RATE_MCS_HT40_MSK) + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (rate_n_flags & RATE_MCS_DUP_MSK) + r->flags |= IEEE80211_TX_RC_DUP_DATA; + if (rate_n_flags & RATE_MCS_SGI_MSK) + r->flags |= IEEE80211_TX_RC_SHORT_GI; + r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); } /** @@ -837,15 +850,12 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; + struct iwl_tx_queue *txq = NULL; struct iwl_ht_agg *agg; - struct sk_buff_head reclaimed_skbs; - struct ieee80211_tx_info *info; - struct ieee80211_hdr *hdr; - struct sk_buff *skb; - unsigned long flags; + int index; int sta_id; int tid; - int freed; + unsigned long flags; /* "flow" corresponds to Tx queue */ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); @@ -854,18 +864,16 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= hw_params(priv).max_txq_num) { + if (scd_flow >= priv->hw_params.max_txq_num) { IWL_ERR(priv, "BUG_ON scd_flow is bigger than number of queues\n"); return; } + txq = &priv->txq[scd_flow]; sta_id = ba_resp->sta_id; tid = ba_resp->tid; - agg = &priv->shrd->tid_data[sta_id][tid].agg; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - + agg = &priv->stations[sta_id].tid[tid].agg; if (unlikely(agg->txq_id != scd_flow)) { /* * FIXME: this is a uCode bug which need to be addressed, @@ -876,83 +884,88 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "BA scd_flow %d does not match txq_id %d\n", scd_flow, agg->txq_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return; } - if (unlikely(!agg->wait_for_ba)) { - if (unlikely(ba_resp->bitmap)) - IWL_ERR(priv, "Received BA when not expected\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return; - } + /* Find index just before block-ack window */ + index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); + + spin_lock_irqsave(&priv->sta_lock, flags); IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32, ba_resp->sta_id); - IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " - "scd_flow = %d, scd_ssn = %d\n", + IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " + "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl, (unsigned long long)le64_to_cpu(ba_resp->bitmap), ba_resp->scd_flow, ba_resp->scd_ssn); + IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", + agg->start_idx, + (unsigned long long)agg->bitmap); - /* Mark that the expected block-ack response arrived */ - agg->wait_for_ba = 0; - - /* Sanity check values reported by uCode */ - if (ba_resp->txed_2_done > ba_resp->txed) { - IWL_DEBUG_TX_REPLY(priv, - "bogus sent(%d) and ack(%d) count\n", - ba_resp->txed, ba_resp->txed_2_done); - /* - * set txed_2_done = txed, - * so it won't impact rate scale - */ - ba_resp->txed = ba_resp->txed_2_done; - } - IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", - ba_resp->txed, ba_resp->txed_2_done); - - __skb_queue_head_init(&reclaimed_skbs); + /* Update driver's record of ACK vs. not for each frame in window */ + iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); /* Release all TFDs before the SSN, i.e. all TFDs in front of * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ - iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn, - 0, &reclaimed_skbs); - freed = 0; - while (!skb_queue_empty(&reclaimed_skbs)) { + if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { + /* calculate mac80211 ampdu sw queue to wake */ + int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - skb = __skb_dequeue(&reclaimed_skbs); - hdr = (struct ieee80211_hdr *)skb->data; + if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && + priv->mac80211_registered && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); - if (ieee80211_is_data_qos(hdr->frame_control)) - freed++; - else - WARN_ON_ONCE(1); - - if (freed == 0) { - /* this is the first skb we deliver in this batch */ - /* put the rate scaling data there */ - info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; - info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_len = ba_resp->txed_2_done; - info->status.ampdu_len = ba_resp->txed; - iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, - info); - } + iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); + } + + spin_unlock_irqrestore(&priv->sta_lock, flags); +} - info = IEEE80211_SKB_CB(skb); - kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); +#ifdef CONFIG_IWLWIFI_DEBUG +const char *iwl_get_tx_fail_reason(u32 status) +{ +#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x - ieee80211_tx_status_irqsafe(priv->hw, skb); + switch (status & TX_STATUS_MSK) { + case TX_STATUS_SUCCESS: + return "SUCCESS"; + TX_STATUS_POSTPONE(DELAY); + TX_STATUS_POSTPONE(FEW_BYTES); + TX_STATUS_POSTPONE(BT_PRIO); + TX_STATUS_POSTPONE(QUIET_PERIOD); + TX_STATUS_POSTPONE(CALC_TTAK); + TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); + TX_STATUS_FAIL(SHORT_LIMIT); + TX_STATUS_FAIL(LONG_LIMIT); + TX_STATUS_FAIL(FIFO_UNDERRUN); + TX_STATUS_FAIL(DRAIN_FLOW); + TX_STATUS_FAIL(RFKILL_FLUSH); + TX_STATUS_FAIL(LIFE_EXPIRE); + TX_STATUS_FAIL(DEST_PS); + TX_STATUS_FAIL(HOST_ABORTED); + TX_STATUS_FAIL(BT_RETRY); + TX_STATUS_FAIL(STA_INVALID); + TX_STATUS_FAIL(FRAG_DROPPED); + TX_STATUS_FAIL(TID_DISABLE); + TX_STATUS_FAIL(FIFO_FLUSHED); + TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); + TX_STATUS_FAIL(PASSIVE_NO_RX); + TX_STATUS_FAIL(NO_BEACON_ON_RADAR); } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + return "UNKNOWN"; + +#undef TX_STATUS_FAIL +#undef TX_STATUS_POSTPONE } +#endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index ea31d7674df3..a895a099d086 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -40,7 +40,6 @@ #include "iwl-agn.h" #include "iwl-agn-calib.h" #include "iwl-trans.h" -#include "iwl-fh.h" static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, @@ -85,36 +84,36 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, priv->ucode_write_complete = 0; - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), (iwl_get_dma_hi_addr(phy_addr) << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); - ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue, + ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); if (ret == -ERESTARTSYS) { IWL_ERR(priv, "Could not load the %s uCode section due " @@ -194,7 +193,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -292,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return iwl_trans_send_cmd_pdu(trans(priv), + return trans_send_cmd_pdu(&priv->trans, COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -325,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, sizeof(iwlagn_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans(priv), + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) IWL_ERR(priv, "failed to send BT prio tbl command\n"); @@ -338,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) @@ -349,21 +348,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) static int iwlagn_alive_notify(struct iwl_priv *priv) { - struct iwl_rxon_context *ctx; int ret; - if (!priv->tx_cmd_pool) - priv->tx_cmd_pool = - kmem_cache_create("iwlagn_dev_cmd", - sizeof(struct iwl_device_cmd), - sizeof(void *), 0, NULL); - - if (!priv->tx_cmd_pool) - return -ENOMEM; - - iwl_trans_tx_start(trans(priv)); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; + trans_tx_start(&priv->trans); ret = iwlagn_send_wimax_coex(priv); if (ret) @@ -382,7 +369,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwl_verify_inst_sparse(struct iwl_priv *priv, +static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; @@ -396,9 +383,9 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -417,14 +404,14 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); - iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); for (offs = 0; offs < len && errors < 20; offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERR(priv, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", @@ -440,7 +427,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, */ static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) { - if (!iwl_verify_inst_sparse(priv, &img->code)) { + if (!iwlcore_verify_inst_sparse(priv, &img->code)) { IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); return 0; } @@ -491,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = iwl_trans_start_device(trans(priv)); + ret = trans_start_device(&priv->trans); if (ret) return ret; @@ -508,7 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - iwl_trans_kick_nic(trans(priv)); + trans_kick_nic(&priv->trans); /* * Some things may run in the background now, but we @@ -558,7 +545,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* No init ucode required? Curious, but maybe ok */ if (!priv->ucode_init.code.len) @@ -593,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index 7f6c58ebbc44..33894dde1ae3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -51,7 +51,6 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-shared.h" #include "iwl-bus.h" #include "iwl-trans.h" @@ -80,6 +79,9 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); +static int iwlagn_ant_coupling; +static bool iwlagn_bt_ch_announce = 1; + void iwl_update_chain_flags(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; @@ -135,7 +137,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) * beacon contents. */ - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); @@ -180,7 +182,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate = info->control.rates[0].idx; priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* In mac80211, rates for 5 GHz start at 0 */ @@ -200,7 +202,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -209,7 +211,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "updating beacon w/o beacon context!\n"); goto out; @@ -239,7 +241,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwlagn_send_beacon_cmd(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -247,11 +249,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_runtime_config); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwlagn_send_advance_bt_config(priv); } @@ -262,13 +264,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) goto out; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) goto out; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", @@ -286,7 +288,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) iwlagn_send_advance_bt_config(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -303,11 +305,11 @@ static void iwl_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwl_send_statistics_request(priv, CMD_ASYNC, false); @@ -329,14 +331,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); - if (iwl_grab_nic_access(bus(priv))) { - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (iwl_grab_nic_access(priv)) { + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); return; } /* Set starting address; reads will auto-increment */ - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -344,20 +346,20 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } } /* Allow device to power down */ - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } static void iwl_continuous_event_trace(struct iwl_priv *priv) @@ -370,12 +372,10 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - capacity = iwl_read_targ_mem(bus(priv), base); - num_wraps = iwl_read_targ_mem(bus(priv), - base + (2 * sizeof(u32))); - mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(priv), - base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(priv, base); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); } else return; @@ -426,7 +426,7 @@ static void iwl_bg_ucode_trace(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->event_log.ucode_trace) { @@ -442,11 +442,11 @@ static void iwl_bg_tx_flush(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tx_flush); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* do nothing if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); @@ -475,15 +475,14 @@ static void iwl_bg_tx_flush(struct work_struct *work) static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_shared *shrd = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd)); + struct iwl_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); } static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_shared *shrd = dev_get_drvdata(d); - struct iwl_priv *priv = shrd->priv; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -491,9 +490,9 @@ static ssize_t store_debug_level(struct device *d, if (ret) IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); else { - shrd->dbg_level_dev = val; + priv->debug_level = val; if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(shrd->priv, + IWL_ERR(priv, "Not enough memory to generate traffic log\n"); } return strnlen(buf, count); @@ -509,10 +508,9 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_shared *shrd = dev_get_drvdata(d); - struct iwl_priv *priv = shrd->priv; + struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", priv->temperature); @@ -525,7 +523,7 @@ static ssize_t show_tx_power(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return sprintf(buf, "off\n"); else return sprintf(buf, "%d\n", priv->tx_power_user_lmt); @@ -617,15 +615,33 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) { + static const u8 iwlagn_bss_ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + }; + static const u8 iwlagn_bss_ac_to_queue[] = { + 0, 1, 2, 3, + }; + static const u8 iwlagn_pan_ac_to_fifo[] = { + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_BK_IPAN, + }; + static const u8 iwlagn_pan_ac_to_queue[] = { + 7, 6, 5, 4, + }; int i; /* * The default context is always valid, * the PAN context depends on uCode. */ - priv->shrd->valid_contexts = BIT(IWL_RXON_CTX_BSS); + priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) - priv->shrd->valid_contexts |= BIT(IWL_RXON_CTX_PAN); + priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); for (i = 0; i < NUM_IWL_RXON_CTX; i++) priv->contexts[i].ctxid = i; @@ -638,6 +654,8 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = @@ -657,6 +675,9 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; + priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; priv->contexts[IWL_RXON_CTX_PAN].interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); @@ -797,6 +818,8 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, return 0; } +static int iwlagn_wanted_ucode_alternative = 1; + static int iwlagn_load_firmware(struct iwl_priv *priv, const struct firmware *ucode_raw, struct iwlagn_firmware_pieces *pieces, @@ -806,8 +829,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, struct iwl_ucode_tlv *tlv; size_t len = ucode_raw->size; const u8 *data; - int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; - int tmp; + int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; u64 alternatives; u32 tlv_len; enum iwl_ucode_tlv_type tlv_type; @@ -1128,25 +1150,25 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_data_size); /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > hw_params(priv).max_inst_size) { + if (pieces.inst_size > priv->hw_params.max_inst_size) { IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", pieces.inst_size); goto try_again; } - if (pieces.data_size > hw_params(priv).max_data_size) { + if (pieces.data_size > priv->hw_params.max_data_size) { IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", pieces.data_size); goto try_again; } - if (pieces.init_size > hw_params(priv).max_inst_size) { + if (pieces.init_size > priv->hw_params.max_inst_size) { IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", pieces.init_size); goto try_again; } - if (pieces.init_data_size > hw_params(priv).max_data_size) { + if (pieces.init_data_size > priv->hw_params.max_data_size) { IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", pieces.init_data_size); goto try_again; @@ -1223,10 +1245,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; } else { priv->sta_key_max_num = STA_KEY_MAX_NUM; - priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; } /* @@ -1287,6 +1309,364 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) release_firmware(ucode_raw); } +static const char * const desc_lookup_text[] = { + "OK", + "FAIL", + "BAD_PARAM", + "BAD_CHECKSUM", + "NMI_INTERRUPT_WDG", + "SYSASSERT", + "FATAL_ERROR", + "BAD_COMMAND", + "HW_ERROR_TUNE_LOCK", + "HW_ERROR_TEMPERATURE", + "ILLEGAL_CHAN_FREQ", + "VCC_NOT_STABLE", + "FH_ERROR", + "NMI_INTERRUPT_HOST", + "NMI_INTERRUPT_ACTION_PT", + "NMI_INTERRUPT_UNKNOWN", + "UCODE_VERSION_MISMATCH", + "HW_ERROR_ABS_LOCK", + "HW_ERROR_CAL_LOCK_FAIL", + "NMI_INTERRUPT_INST_ACTION_PT", + "NMI_INTERRUPT_DATA_ACTION_PT", + "NMI_TRM_HW_ER", + "NMI_INTERRUPT_TRM", + "NMI_INTERRUPT_BREAK_POINT", + "DEBUG_0", + "DEBUG_1", + "DEBUG_2", + "DEBUG_3", +}; + +static struct { char *name; u8 num; } advanced_lookup[] = { + { "NMI_INTERRUPT_WDG", 0x34 }, + { "SYSASSERT", 0x35 }, + { "UCODE_VERSION_MISMATCH", 0x37 }, + { "BAD_COMMAND", 0x38 }, + { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, + { "FATAL_ERROR", 0x3D }, + { "NMI_TRM_HW_ERR", 0x46 }, + { "NMI_INTERRUPT_TRM", 0x4C }, + { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, + { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, + { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, + { "NMI_INTERRUPT_HOST", 0x66 }, + { "NMI_INTERRUPT_ACTION_PT", 0x7C }, + { "NMI_INTERRUPT_UNKNOWN", 0x84 }, + { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, + { "ADVANCED_SYSASSERT", 0 }, +}; + +static const char *desc_lookup(u32 num) +{ + int i; + int max = ARRAY_SIZE(desc_lookup_text); + + if (num < max) + return desc_lookup_text[num]; + + max = ARRAY_SIZE(advanced_lookup) - 1; + for (i = 0; i < max; i++) { + if (advanced_lookup[i].num == num) + break; + } + return advanced_lookup[i].name; +} + +#define ERROR_START_OFFSET (1 * sizeof(u32)) +#define ERROR_ELEM_SIZE (7 * sizeof(u32)) + +void iwl_dump_nic_error_log(struct iwl_priv *priv) +{ + u32 base; + struct iwl_error_event_table table; + + base = priv->device_pointers.error_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_errlog_ptr; + } else { + if (!base) + base = priv->inst_errlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Not valid error log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return; + } + + iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); + + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->status, table.valid); + } + + priv->isr_stats.err_code = table.error_id; + + trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, + table.data1, table.data2, table.line, + table.blink1, table.blink2, table.ilink1, + table.ilink2, table.bcon_time, table.gp1, + table.gp2, table.gp3, table.ucode_ver, + table.hw_ver, table.brd_ver); + IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + desc_lookup(table.error_id)); + IWL_ERR(priv, "0x%08X | uPc\n", table.pc); + IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(priv, "0x%08X | data1\n", table.data1); + IWL_ERR(priv, "0x%08X | data2\n", table.data2); + IWL_ERR(priv, "0x%08X | line\n", table.line); + IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); +} + +#define EVENT_START_OFFSET (4 * sizeof(u32)) + +/** + * iwl_print_event_log - Dump error event log to syslog + * + */ +static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode, + int pos, char **buf, size_t bufsz) +{ + u32 i; + u32 base; /* SRAM byte address of event log header */ + u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ + u32 ptr; /* SRAM byte address of log data */ + u32 ev, time, data; /* event log data */ + unsigned long reg_flags; + + if (num_events == 0) + return pos; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_evtlog_ptr; + } else { + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (mode == 0) + event_size = 2 * sizeof(u32); + else + event_size = 3 * sizeof(u32); + + ptr = base + EVENT_START_OFFSET + (start_idx * event_size); + + /* Make sure device is powered up for SRAM reads */ + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + + /* Set starting address; reads will auto-increment */ + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + rmb(); + + /* "time" is actually "data" for mode 0 (no timestamp). + * place event id # at far right for easier visual parsing. */ + for (i = 0; i < num_events; i++) { + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (mode == 0) { + /* data, ev */ + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOG:0x%08x:%04u\n", + time, ev); + } else { + trace_iwlwifi_dev_ucode_event(priv, 0, + time, ev); + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", + time, ev); + } + } else { + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + } else { + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + trace_iwlwifi_dev_ucode_event(priv, time, + data, ev); + } + } + } + + /* Allow device to power down */ + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return pos; +} + +/** + * iwl_print_last_event_logs - Dump the newest # of event log to syslog + */ +static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, + u32 num_wraps, u32 next_entry, + u32 size, u32 mode, + int pos, char **buf, size_t bufsz) +{ + /* + * display the newest DEFAULT_LOG_ENTRIES entries + * i.e the entries just before the next ont that uCode would fill. + */ + if (num_wraps) { + if (next_entry < size) { + pos = iwl_print_event_log(priv, + capacity - (size - next_entry), + size - next_entry, mode, + pos, buf, bufsz); + pos = iwl_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); + } else + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } else { + if (next_entry < size) { + pos = iwl_print_event_log(priv, 0, next_entry, + mode, pos, buf, bufsz); + } else { + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } + } + return pos; +} + +#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) + +int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display) +{ + u32 base; /* SRAM byte address of event log header */ + u32 capacity; /* event log capacity in # entries */ + u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ + u32 num_wraps; /* # times uCode wrapped to top of log */ + u32 next_entry; /* index of next entry to be written by uCode */ + u32 size; /* # entries that we'll print */ + u32 logsize; + int pos = 0; + size_t bufsz = 0; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + logsize = priv->init_evtlog_size; + if (!base) + base = priv->init_evtlog_ptr; + } else { + logsize = priv->inst_evtlog_size; + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Invalid event log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return -EINVAL; + } + + /* event log header */ + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + + if (capacity > logsize) { + IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", + capacity, logsize); + capacity = logsize; + } + + if (next_entry > logsize) { + IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", + next_entry, logsize); + next_entry = logsize; + } + + size = num_wraps ? capacity : next_entry; + + /* bail out if nothing in log */ + if (size == 0) { + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); + return pos; + } + + /* enable/disable bt channel inhibition */ + priv->bt_ch_announce = iwlagn_bt_ch_announce; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#else + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#endif + IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", + size); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + if (full_log) + bufsz = capacity * 48; + else + bufsz = size * 48; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + } + if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { + /* + * if uCode has wrapped back to top of log, + * start at the oldest entry, + * i.e the next one that uCode would fill. + */ + if (num_wraps) + pos = iwl_print_event_log(priv, next_entry, + capacity - next_entry, mode, + pos, buf, bufsz); + /* (then/else) start at top of log */ + pos = iwl_print_event_log(priv, 0, + next_entry, mode, pos, buf, bufsz); + } else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#endif + return pos; +} + static void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; @@ -1294,43 +1674,44 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) unsigned long flags; int ret = 0; - spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); priv->thermal_throttle.ct_kill_toggle = false; if (priv->cfg->base_params->support_ct_kill_exit) { adv_cmd.critical_temperature_enter = - cpu_to_le32(hw_params(priv).ct_kill_threshold); + cpu_to_le32(priv->hw_params.ct_kill_threshold); adv_cmd.critical_temperature_exit = - cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); + cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, critical temperature enter is %d," - "exit is %d\n", - hw_params(priv).ct_kill_threshold, - hw_params(priv).ct_kill_exit_threshold); + "succeeded, " + "critical temperature enter is %d," + "exit is %d\n", + priv->hw_params.ct_kill_threshold, + priv->hw_params.ct_kill_exit_threshold); } else { cmd.critical_temperature_R = - cpu_to_le32(hw_params(priv).ct_kill_threshold); + cpu_to_le32(priv->hw_params.ct_kill_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature is %d\n", - hw_params(priv).ct_kill_threshold); + "succeeded, " + "critical temperature is %d\n", + priv->hw_params.ct_kill_threshold); } } @@ -1347,7 +1728,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -1359,7 +1740,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) if (IWL_UCODE_API(priv->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return iwl_trans_send_cmd_pdu(trans(priv), + return trans_send_cmd_pdu(&priv->trans, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, sizeof(struct iwl_tx_ant_config_cmd), @@ -1381,17 +1762,17 @@ int iwl_alive_start(struct iwl_priv *priv) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; /*TODO: this should go to the transport layer */ - iwl_reset_ict(trans(priv)); + iwl_reset_ict(priv); IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->shrd->status); + set_bit(STATUS_ALIVE, &priv->status); /* Enable watchdog to monitor the driver tx queues */ iwl_setup_watchdog(priv); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -ERFKILL; /* download priority table before any calibration request */ @@ -1428,9 +1809,8 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); } - if (hw_params(priv).calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, - hw_params(priv).calib_rt_cfg); + if (priv->hw_params.calib_rt_cfg) + iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); ieee80211_wake_queues(priv->hw); @@ -1439,7 +1819,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) { + if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -1454,12 +1834,12 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - if (!priv->shrd->wowlan) { + if (!priv->wowlan) { /* WoWLAN ucode will not reply in the same way, skip it */ iwl_reset_run_time_calib(priv); } - set_bit(STATUS_READY, &priv->shrd->status); + set_bit(STATUS_READY, &priv->status); /* Configure the adapter for unassociated operation */ ret = iwlagn_commit_rxon(priv, ctx); @@ -1491,8 +1871,7 @@ static void __iwl_down(struct iwl_priv *priv) */ ieee80211_remain_on_channel_expired(priv->hw); - exit_pending = - test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ @@ -1517,23 +1896,22 @@ static void __iwl_down(struct iwl_priv *priv) /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); /* Clear out all status bits but a few that are stable across reset */ - priv->shrd->status &= - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << + priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) << + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->shrd->status) << + test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << + test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -1541,9 +1919,9 @@ static void __iwl_down(struct iwl_priv *priv) static void iwl_down(struct iwl_priv *priv) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); __iwl_down(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); } @@ -1555,9 +1933,9 @@ static int __iwl_up(struct iwl_priv *priv) struct iwl_rxon_context *ctx; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } @@ -1590,9 +1968,9 @@ static int __iwl_up(struct iwl_priv *priv) return 0; error: - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + set_bit(STATUS_EXIT_PENDING, &priv->status); __iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); IWL_ERR(priv, "Unable to initialize device.\n"); return ret; @@ -1610,11 +1988,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, run_time_calib_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status)) { - mutex_unlock(&priv->shrd->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status)) { + mutex_unlock(&priv->mutex); return; } @@ -1623,7 +2001,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) iwl_sensitivity_calibration(priv); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwlagn_prepare_restart(struct iwl_priv *priv) @@ -1635,7 +2013,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv) u8 bt_status; bool bt_is_sco; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); for_each_context(priv, ctx) ctx->vif = NULL; @@ -1669,13 +2047,13 @@ static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - mutex_lock(&priv->shrd->mutex); + if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + mutex_lock(&priv->mutex); iwlagn_prepare_restart(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { @@ -1863,7 +2241,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); return ret; } - priv->shrd->mac80211_registered = 1; + priv->mac80211_registered = 1; return 0; } @@ -1877,16 +2255,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = __iwl_up(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) return ret; IWL_DEBUG_INFO(priv, "Start UP work done.\n"); /* Now we should be done, and the READY bit should be set. */ - if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) + if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) ret = -EIO; iwlagn_led_enable(priv); @@ -1909,11 +2287,11 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) iwl_down(priv); - flush_workqueue(priv->shrd->workqueue); + flush_workqueue(priv->workqueue); /* User space software may expect getting rfkill changes * even if interface is down */ - iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1957,7 +2335,7 @@ static int iwlagn_send_patterns(struct iwl_priv *priv, } cmd.data[0] = pattern_cmd; - err = iwl_trans_send_cmd(trans(priv), &cmd); + err = trans_send_cmd(&priv->trans, &cmd); kfree(pattern_cmd); return err; } @@ -1972,7 +2350,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, if (iwlagn_mod_params.sw_crypto) return; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) goto out; @@ -1983,7 +2361,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, priv->have_rekey_data = true; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } struct wowlan_key_data { @@ -2021,7 +2399,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, u16 p1k[IWLAGN_P1K_SIZE]; int ret, i; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && @@ -2126,7 +2504,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static int iwlagn_mac_suspend(struct ieee80211_hw *hw, @@ -2151,7 +2529,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, if (WARN_ON(!wowlan)) return -EINVAL; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* Don't attempt WoWLAN when not associated, tear down instead. */ if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || @@ -2180,7 +2558,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * since the uCode will add 0x10 before using the value. */ for (i = 0; i < 8; i++) { - seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; + seq = priv->stations[IWL_AP_ID].tid[i].seq_number; seq -= 0x10; wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); } @@ -2212,9 +2590,9 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, memcpy(&rxon, &ctx->active, sizeof(rxon)); - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); - priv->shrd->wowlan = true; + priv->wowlan = true; ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan, IWL_UCODE_WOWLAN); @@ -2245,11 +2623,11 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * constraints. Since we're in the suspend path * that isn't really a problem though. */ - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); ieee80211_iter_keys(priv->hw, ctx->vif, iwlagn_wowlan_program_keys, &key_data); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (key_data.error) { ret = -EIO; goto error; @@ -2264,13 +2642,13 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, .len[0] = sizeof(*key_data.rsc_tsc), }; - ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); + ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd); if (ret) goto error; } if (key_data.use_tkip) { - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_TKIP_PARAMS, CMD_SYNC, sizeof(tkip_cmd), &tkip_cmd); @@ -2286,7 +2664,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); kek_kck_cmd.replay_ctr = priv->replay_ctr; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_KEK_KCK_MATERIAL, CMD_SYNC, sizeof(kek_kck_cmd), &kek_kck_cmd); @@ -2295,7 +2673,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, } } - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER, CMD_SYNC, sizeof(wakeup_filter_cmd), &wakeup_filter_cmd); if (ret) @@ -2308,17 +2686,17 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, device_set_wakeup_enable(priv->bus->dev, true); /* Now let the ucode operate on its own */ - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); goto out; error: - priv->shrd->wowlan = false; + priv->wowlan = false; iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); kfree(key_data.rsc_tsc); return ret; } @@ -2332,21 +2710,21 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) u32 base, status = 0xffffffff; int ret = -EIO; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - ret = iwl_grab_nic_access_silent(bus(priv)); + spin_lock_irqsave(&priv->reg_lock, flags); + ret = iwl_grab_nic_access_silent(priv); if (ret == 0) { - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); - status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus(priv)); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); #ifdef CONFIG_IWLWIFI_DEBUGFS if (ret == 0) { @@ -2357,7 +2735,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) if (priv->wowlan_sram) _iwl_read_targ_mem_words( - bus(priv), 0x800000, priv->wowlan_sram, + priv, 0x800000, priv->wowlan_sram, priv->ucode_wowlan.data.len / 4); } #endif @@ -2366,7 +2744,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - priv->shrd->wowlan = false; + priv->wowlan = false; device_set_wakeup_enable(priv->bus->dev, false); @@ -2376,7 +2754,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) iwl_connection_init_rx_config(priv, ctx); iwlagn_set_rxon_chain(priv, ctx); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); ieee80211_resume_disconnect(vif); @@ -2445,7 +2823,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) return 0; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); @@ -2496,7 +2874,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -2511,7 +2889,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; int ret = -EINVAL; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); @@ -2519,7 +2896,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)) return -EACCES; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -2529,7 +2906,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); ret = iwl_sta_rx_agg_stop(priv, sta, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; break; case IEEE80211_AMPDU_TX_START: @@ -2549,7 +2926,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", priv->agg_tids_count); } - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; if (priv->cfg->ht_params && priv->cfg->ht_params->use_rts_for_aggregation) { @@ -2565,8 +2942,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), - tid, buf_size); + trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid, + buf_size); /* * If the limit is 0, then it wasn't initialised yet, @@ -2610,7 +2987,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, ret = 0; break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -2628,7 +3005,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", sta->addr); sta_priv->common.sta_id = IWL_INVALID_STATION; @@ -2643,7 +3020,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -2653,7 +3030,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return 0; } @@ -2679,14 +3056,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) goto out; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status) || - test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_is_associated_ctx(ctx)) @@ -2705,7 +3082,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; } - spin_lock_irq(&priv->shrd->lock); + spin_lock_irq(&priv->lock); priv->current_ht_config.smps = conf->smps_mode; @@ -2735,23 +3112,23 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); - spin_unlock_irq(&priv->shrd->lock); + spin_unlock_irq(&priv->lock); iwl_set_rate(priv); /* * at this point, staging_rxon has the * configuration for channel switch */ - set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = cpu_to_le16(ch); if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { - clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = 0; ieee80211_chswitch_done(ctx->vif, false); } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -2781,7 +3158,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, #undef CHK - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; @@ -2793,7 +3170,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, */ } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); /* * Receiving all multicast frames is always enabled by the @@ -2809,14 +3186,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); goto done; } - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); goto done; } @@ -2833,9 +3210,9 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) } } IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); - iwl_trans_wait_tx_queue_empty(trans(priv)); + iwlagn_wait_tx_queue_empty(priv); done: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -2843,7 +3220,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->hw_roc_setup) return; @@ -2866,9 +3243,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, hw_roc_disable_work.work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, @@ -2880,13 +3257,13 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; int err = 0; - if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) + if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) return -EOPNOTSUPP; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * TODO: Remove this hack! Firmware needs to be updated @@ -2897,7 +3274,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) duration = 80; - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { err = -EBUSY; goto out; } @@ -2936,7 +3313,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, iwlagn_disable_roc(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return err; } @@ -2945,83 +3322,17 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; - if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) + if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return 0; } -static int iwl_mac_tx_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - const u8 *bssid, enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - int ret; - u8 sta_id; - - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) { - ret = 0; - goto out; - } - - if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { - ret = -EBUSY; - goto out; - } - - ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); - if (ret) - goto out; - - if (WARN_ON(sta_id != ctx->ap_sta_id)) { - ret = -EIO; - goto out_remove_sta; - } - - memcpy(ctx->bssid, bssid, ETH_ALEN); - ctx->preauth_bssid = true; - - ret = iwlagn_commit_rxon(priv, ctx); - - if (ret == 0) - goto out; - - out_remove_sta: - iwl_remove_station(priv, sta_id, bssid); - out: - mutex_unlock(&priv->shrd->mutex); - return ret; -} - -static void iwl_mac_finish_tx_sync(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *bssid, - enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) - goto out; - - iwl_remove_station(priv, ctx->ap_sta_id, bssid); - ctx->preauth_bssid = false; - /* no need to commit */ - out: - mutex_unlock(&priv->shrd->mutex); -} - /***************************************************************************** * * driver setup and teardown @@ -3030,9 +3341,9 @@ static void iwl_mac_finish_tx_sync(struct ieee80211_hw *hw, static void iwl_setup_deferred_work(struct iwl_priv *priv) { - priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME); + priv->workqueue = create_singlethread_workqueue(DRV_NAME); - init_waitqueue_head(&priv->shrd->wait_command_queue); + init_waitqueue_head(&priv->wait_command_queue); INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); @@ -3104,9 +3415,10 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - spin_lock_init(&priv->shrd->sta_lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); - mutex_init(&priv->shrd->mutex); + mutex_init(&priv->mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; @@ -3147,7 +3459,7 @@ static int iwl_init_drv(struct iwl_priv *priv) goto err; } - ret = iwl_init_geos(priv); + ret = iwlcore_init_geos(priv); if (ret) { IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; @@ -3165,10 +3477,8 @@ static int iwl_init_drv(struct iwl_priv *priv) static void iwl_uninit_drv(struct iwl_priv *priv) { iwl_calib_free_results(priv); - iwl_free_geos(priv); + iwlcore_free_geos(priv); iwl_free_channel_map(priv); - if (priv->tx_cmd_pool) - kmem_cache_destroy(priv->tx_cmd_pool); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -3181,7 +3491,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { @@ -3196,7 +3506,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, "ignoring RSSI callback\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } struct ieee80211_ops iwlagn_hw_ops = { @@ -3230,38 +3540,27 @@ struct ieee80211_ops iwlagn_hw_ops = { .rssi_callback = iwl_mac_rssi_callback, CFG80211_TESTMODE_CMD(iwl_testmode_cmd) CFG80211_TESTMODE_DUMP(iwl_testmode_dump) - .tx_sync = iwl_mac_tx_sync, - .finish_tx_sync = iwl_mac_finish_tx_sync, }; static u32 iwl_hw_detect(struct iwl_priv *priv) { - return iwl_read32(bus(priv), CSR_HW_REV); + return iwl_read32(priv, CSR_HW_REV); } -/* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_4K (4 * 1024) -#define IWL_RX_BUF_SIZE_8K (8 * 1024) - static int iwl_set_hw_params(struct iwl_priv *priv) { + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; if (iwlagn_mod_params.amsdu_size_8K) - hw_params(priv).rx_page_order = - get_order(IWL_RX_BUF_SIZE_8K); + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); else - hw_params(priv).rx_page_order = - get_order(IWL_RX_BUF_SIZE_4K); + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); + + priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; - hw_params(priv).num_ampdu_queues = - priv->cfg->base_params->num_of_ampdu_queues; - hw_params(priv).shadow_reg_enable = - priv->cfg->base_params->shadow_reg_enable; - hw_params(priv).sku = priv->cfg->sku; - hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout; - /* Device-specific setup */ return priv->cfg->lib->set_hw_params(priv); } @@ -3288,8 +3587,7 @@ static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) return hw; } -int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, - struct iwl_cfg *cfg) +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) { int err = 0; struct iwl_priv *priv; @@ -3308,17 +3606,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, priv = hw->priv; priv->bus = bus; - priv->shrd = &priv->_shrd; - priv->shrd->bus = bus; - priv->shrd->priv = priv; - priv->shrd->hw = hw; - bus_set_drv_data(priv->bus, priv->shrd); - - priv->shrd->trans = trans_ops->alloc(priv->shrd); - if (priv->shrd->trans == NULL) { - err = -ENOMEM; - goto out_free_traffic_mem; - } + bus_set_drv_data(priv->bus, priv); /* At this point both hw and priv are allocated. */ @@ -3326,15 +3614,15 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; + priv->inta_mask = CSR_INI_SET_MASK; /* is antenna coupling more than 35dB ? */ priv->bt_ant_couple_ok = - (iwlagn_mod_params.ant_coupling > - IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? - true : false; + (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? + true : false; /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; + priv->bt_ch_announce = iwlagn_bt_ch_announce; IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", (priv->bt_ch_announce) ? "On" : "Off"); @@ -3344,15 +3632,15 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ - spin_lock_init(&bus(priv)->reg_lock); - spin_lock_init(&priv->shrd->lock); + spin_lock_init(&priv->reg_lock); + spin_lock_init(&priv->lock); /* * stop and reset the on-board processor just in case it is in a * strange state ... like being left stranded by a primary kernel * and this is now the kdump kernel trying to start up */ - iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /*********************** * 3. Read REV register @@ -3361,11 +3649,11 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - err = iwl_trans_request_irq(trans(priv)); + err = iwl_trans_register(&priv->trans, priv); if (err) - goto out_free_trans; + goto out_free_traffic_mem; - if (iwl_trans_prepare_card_hw(trans(priv))) { + if (trans_prepare_card_hw(&priv->trans)) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); goto out_free_trans; @@ -3433,14 +3721,13 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(priv), - CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); else - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); iwl_power_initialize(priv); iwl_tt_initialize(priv); @@ -3454,13 +3741,13 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, return 0; out_destroy_workqueue: - destroy_workqueue(priv->shrd->workqueue); - priv->shrd->workqueue = NULL; + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; iwl_uninit_drv(priv); out_free_eeprom: iwl_eeprom_free(priv); out_free_trans: - iwl_trans_free(trans(priv)); + trans_free(&priv->trans); out_free_traffic_mem: iwl_free_traffic_mem(priv); ieee80211_free_hw(priv->hw); @@ -3470,6 +3757,8 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, void __devexit iwl_remove(struct iwl_priv * priv) { + unsigned long flags; + wait_for_completion(&priv->firmware_loading_complete); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); @@ -3482,36 +3771,48 @@ void __devexit iwl_remove(struct iwl_priv * priv) * to be called and iwl_down since we are removing the device * we need to set STATUS_EXIT_PENDING bit. */ - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + set_bit(STATUS_EXIT_PENDING, &priv->status); iwl_testmode_cleanup(priv); iwl_leds_exit(priv); - if (priv->shrd->mac80211_registered) { + if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - priv->shrd->mac80211_registered = 0; + priv->mac80211_registered = 0; } + /* Reset to low power before unloading driver. */ + iwl_apm_stop(priv); + iwl_tt_exit(priv); - /*This will stop the queues, move the device to low power state */ - iwl_trans_stop_device(trans(priv)); + /* make sure we flush any pending irq or + * tasklet for the driver + */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + trans_sync_irq(&priv->trans); iwl_dealloc_ucode(priv); + trans_rx_free(&priv->trans); + trans_tx_free(&priv->trans); + iwl_eeprom_free(priv); /*netif_stop_queue(dev); */ - flush_workqueue(priv->shrd->workqueue); + flush_workqueue(priv->workqueue); /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes - * priv->shrd->workqueue... so we can't take down the workqueue + * priv->workqueue... so we can't take down the workqueue * until now... */ - destroy_workqueue(priv->shrd->workqueue); - priv->shrd->workqueue = NULL; + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; iwl_free_traffic_mem(priv); - iwl_trans_free(trans(priv)); + trans_free(&priv->trans); bus_set_drv_data(priv->bus, NULL); @@ -3562,8 +3863,7 @@ module_exit(iwl_exit); module_init(iwl_init); #ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug, iwlagn_mod_params.debug_level, uint, - S_IRUGO | S_IWUSR); +module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif @@ -3579,21 +3879,18 @@ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); -module_param_named(ucode_alternative, - iwlagn_mod_params.wanted_ucode_alternative, - int, S_IRUGO); +module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, + S_IRUGO); MODULE_PARM_DESC(ucode_alternative, "specify ucode alternative to use from ucode file"); -module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling, - int, S_IRUGO); +module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(bt_ch_inhibition, iwlagn_mod_params.bt_ch_announce, - bool, S_IRUGO); +module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); MODULE_PARM_DESC(bt_ch_inhibition, - "Enable BT channel inhibition (default: enable)"); + "Disable BT channel inhibition (default: enable)"); module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); @@ -3639,11 +3936,6 @@ module_param_named(power_level, iwlagn_mod_params.power_level, MODULE_PARM_DESC(power_level, "default power save level (range from 1 - 5, default: 1)"); -module_param_named(auto_agg, iwlagn_mod_params.auto_agg, - bool, S_IRUGO); -MODULE_PARM_DESC(auto_agg, - "enable agg w/o check traffic load (default: enable)"); - /* * For now, keep using power level 1 instead of automatically * adjusting ... diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h index 4bc1f4669e5a..df2960ae92aa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,9 +65,54 @@ #include "iwl-dev.h" +/* configuration for the _agn devices */ +extern struct iwl_cfg iwl5300_agn_cfg; +extern struct iwl_cfg iwl5100_agn_cfg; +extern struct iwl_cfg iwl5350_agn_cfg; +extern struct iwl_cfg iwl5100_bgn_cfg; +extern struct iwl_cfg iwl5100_abg_cfg; +extern struct iwl_cfg iwl5150_agn_cfg; +extern struct iwl_cfg iwl5150_abg_cfg; +extern struct iwl_cfg iwl6005_2agn_cfg; +extern struct iwl_cfg iwl6005_2abg_cfg; +extern struct iwl_cfg iwl6005_2bg_cfg; +extern struct iwl_cfg iwl1030_bgn_cfg; +extern struct iwl_cfg iwl1030_bg_cfg; +extern struct iwl_cfg iwl6030_2agn_cfg; +extern struct iwl_cfg iwl6030_2abg_cfg; +extern struct iwl_cfg iwl6030_2bgn_cfg; +extern struct iwl_cfg iwl6030_2bg_cfg; +extern struct iwl_cfg iwl6000i_2agn_cfg; +extern struct iwl_cfg iwl6000i_2abg_cfg; +extern struct iwl_cfg iwl6000i_2bg_cfg; +extern struct iwl_cfg iwl6000_3agn_cfg; +extern struct iwl_cfg iwl6050_2agn_cfg; +extern struct iwl_cfg iwl6050_2abg_cfg; +extern struct iwl_cfg iwl6150_bgn_cfg; +extern struct iwl_cfg iwl6150_bg_cfg; +extern struct iwl_cfg iwl1000_bgn_cfg; +extern struct iwl_cfg iwl1000_bg_cfg; +extern struct iwl_cfg iwl100_bgn_cfg; +extern struct iwl_cfg iwl100_bg_cfg; +extern struct iwl_cfg iwl130_bgn_cfg; +extern struct iwl_cfg iwl130_bg_cfg; +extern struct iwl_cfg iwl2000_2bgn_cfg; +extern struct iwl_cfg iwl2000_2bg_cfg; +extern struct iwl_cfg iwl2030_2bgn_cfg; +extern struct iwl_cfg iwl2030_2bg_cfg; +extern struct iwl_cfg iwl6035_2agn_cfg; +extern struct iwl_cfg iwl6035_2abg_cfg; +extern struct iwl_cfg iwl6035_2bg_cfg; +extern struct iwl_cfg iwl105_bg_cfg; +extern struct iwl_cfg iwl105_bgn_cfg; +extern struct iwl_cfg iwl135_bg_cfg; +extern struct iwl_cfg iwl135_bgn_cfg; + +extern struct iwl_mod_params iwlagn_mod_params; + extern struct ieee80211_ops iwlagn_hw_ops; -int iwl_reset_ict(struct iwl_trans *trans); +int iwl_reset_ict(struct iwl_priv *priv); static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { @@ -77,6 +122,10 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } +/* tx queue */ +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed); + /* RXON */ int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -98,9 +147,13 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwlagn_ucode_type ucode_type); /* lib */ +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status); +int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); +int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); int iwlagn_send_beacon_cmd(struct iwl_priv *priv); @@ -108,17 +161,25 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv); /* rx */ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); void iwl_setup_rx_handlers(struct iwl_priv *priv); +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* tx */ +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); static inline u32 iwl_tx_status_to_mac80211(u32 status) { @@ -226,7 +287,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) } /* eeprom */ -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); /* notification wait support */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h b/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h index 83aed46673e1..f3ee1c0c004c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -60,22 +60,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#ifndef __iwl_bus_h__ -#define __iwl_bus_h__ +#ifndef __iwl_pci_h__ +#define __iwl_pci_h__ -/*This file includes the declaration that are exported from the bus layer */ - -#include -#include - -struct iwl_shared; struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations * @get_pm_support: must returns true if the bus can go to sleep * @apm_config: will be called during the config of the APM configuration - * @set_drv_data: set the shared data pointer to the bus layer + * @set_drv_data: set the drv_data pointer to the bus layer * @get_hw_id: prints the hw_id in the provided buffer * @write8: write a byte to register at offset ofs * @write32: write a dword to register at offset ofs @@ -84,29 +78,20 @@ struct iwl_bus; struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus); - void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd); + void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); u32 (*read32)(struct iwl_bus *bus, u32 ofs); }; -/** - * struct iwl_bus - bus common data - * @dev - pointer to struct device * that represent the device - * @ops - pointer to iwl_bus_ops - * @shrd - pointer to iwl_shared which holds shared data from the upper layer - * @irq - the irq number for the device - * @reg_lock - protect hw register access - */ struct iwl_bus { /* Common data to all buses */ + void *drv_data; /* driver's context */ struct device *dev; - const struct iwl_bus_ops *ops; - struct iwl_shared *shrd; + struct iwl_bus_ops *ops; unsigned int irq; - spinlock_t reg_lock; /* pointer to bus specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ @@ -123,10 +108,9 @@ static inline void bus_apm_config(struct iwl_bus *bus) bus->ops->apm_config(bus); } -static inline void bus_set_drv_data(struct iwl_bus *bus, - struct iwl_shared *shrd) +static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) { - bus->ops->set_drv_data(bus, shrd); + bus->ops->set_drv_data(bus, drv_data); } static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) @@ -152,4 +136,4 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) int __must_check iwl_pci_register_driver(void); void iwl_pci_unregister_driver(void); -#endif /* __iwl_bus_h__ */ +#endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h index 82bfef4730d5..0016c61b3000 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -69,9 +69,6 @@ #ifndef __iwl_commands_h__ #define __iwl_commands_h__ -#include -#include - struct iwl_priv; /* uCode version contains 4 values: Major/Minor/API/Serial */ @@ -673,6 +670,7 @@ struct iwl_rxon_assoc_cmd { #define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ +#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */ /* * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) @@ -808,7 +806,6 @@ struct iwl_qosparam_cmd { #define IWLAGN_STATION_COUNT 16 #define IWL_INVALID_STATION 255 -#define IWL_MAX_TID_COUNT 9 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) @@ -3213,7 +3210,12 @@ enum iwl_ucode_calib_cfg { IWL_CALIB_CFG_LO_IDX | \ IWL_CALIB_CFG_TX_IQ_IDX | \ IWL_CALIB_CFG_RX_IQ_IDX | \ - IWL_CALIB_CFG_CRYSTAL_IDX) + IWL_CALIB_CFG_NOISE_IDX | \ + IWL_CALIB_CFG_CRYSTAL_IDX | \ + IWL_CALIB_CFG_TEMPERATURE_IDX | \ + IWL_CALIB_CFG_PAPD_IDX | \ + IWL_CALIB_CFG_SENSITIVITY_IDX | \ + IWL_CALIB_CFG_TX_PWR_IDX) #define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0)) @@ -3907,7 +3909,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd { * Union of all expected notifications/responses: * *****************************************************************************/ -#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ struct iwl_rx_packet { /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 9270f990b2dd..e269987cd64c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -42,21 +42,22 @@ #include "iwl-sta.h" #include "iwl-agn.h" #include "iwl-helpers.h" -#include "iwl-shared.h" #include "iwl-agn.h" #include "iwl-trans.h" +u32 iwl_debug_level; + const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ -static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, +static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_info, enum ieee80211_band band) { u16 max_bit_rate = 0; - u8 rx_chains_num = hw_params(priv).rx_chains_num; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 rx_chains_num = priv->hw_params.rx_chains_num; + u8 tx_chains_num = priv->hw_params.tx_chains_num; ht_info->cap = 0; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); @@ -68,7 +69,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; max_bit_rate = MAX_BIT_RATE_20_MHZ; - if (hw_params(priv).ht40_channel & BIT(band)) { + if (priv->hw_params.ht40_channel & BIT(band)) { ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ht_info->cap |= IEEE80211_HT_CAP_SGI_40; ht_info->mcs.rx_mask[4] = 0x01; @@ -106,9 +107,9 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, } /** - * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom + * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -int iwl_init_geos(struct iwl_priv *priv) +int iwlcore_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; @@ -121,7 +122,7 @@ int iwl_init_geos(struct iwl_priv *priv) if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } @@ -145,7 +146,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwl_init_ht_hw_capab(priv, &sband->ht_cap, + iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_5GHZ); sband = &priv->bands[IEEE80211_BAND_2GHZ]; @@ -155,7 +156,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwl_init_ht_hw_capab(priv, &sband->ht_cap, + iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_2GHZ); priv->ieee_channels = channels; @@ -221,19 +222,19 @@ int iwl_init_geos(struct iwl_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } /* - * iwl_free_geos - undo allocations in iwl_init_geos + * iwlcore_free_geos - undo allocations in iwlcore_init_geos */ -void iwl_free_geos(struct iwl_priv *priv) +void iwlcore_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } static bool iwl_is_channel_extension(struct iwl_priv *priv, @@ -325,7 +326,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) conf = ieee80211_get_hw_conf(priv->hw); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -359,7 +360,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else { beacon_int = iwl_adjust_beacon_interval(beacon_int, - IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); + priv->hw_params.max_beacon_itrvl * TIME_UNIT); ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } @@ -378,7 +379,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd, + return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -808,18 +809,17 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, - &priv->shrd->status)) + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); } #ifdef CONFIG_IWLWIFI_DEBUG -void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid) +void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { - struct iwl_rxon_context *ctx = &priv->contexts[ctxid]; struct iwl_rxon_cmd *rxon = &ctx->staging; IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); @@ -857,18 +857,18 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned long reload_jiffies; /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->shrd->status); + set_bit(STATUS_FW_ERROR, &priv->status); /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); iwlagn_abort_notification_waits(priv); /* Keep the restart process from trying to send host * commands by clearing the ready bit */ - clear_bit(STATUS_READY, &priv->shrd->status); + clear_bit(STATUS_READY, &priv->status); - wake_up_interruptible(&priv->shrd->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); if (!ondemand) { /* @@ -891,26 +891,63 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) priv->reload_count = 0; } - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (iwlagn_mod_params.restart_fw) { - IWL_DEBUG_FW_ERRORS(priv, + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); - queue_work(priv->shrd->workqueue, &priv->restart); + queue_work(priv->workqueue, &priv->restart); } else - IWL_DEBUG_FW_ERRORS(priv, + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Detected FW error, but not restarting\n"); } } +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +void iwl_irq_handle_error(struct iwl_priv *priv) +{ + /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ + if (priv->cfg->internal_wimax_coex && + (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & + APMS_CLK_VAL_MRB_FUNC_MODE) || + (iwl_read_prph(priv, APMG_PS_CTRL_REG) & + APMG_PS_CTRL_VAL_RESET_REQ))) { + /* + * Keep the restart process from trying to send host + * commands by clearing the ready bit. + */ + clear_bit(STATUS_READY, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); + IWL_ERR(priv, "RF is used by WiMAX\n"); + return; + } + + IWL_ERR(priv, "Loaded firmware version: %s\n", + priv->hw->wiphy->fw_version); + + iwl_dump_nic_error_log(priv); + iwl_dump_csr(priv); + iwl_dump_fh(priv, NULL, false); + iwl_dump_nic_event_log(priv, false, NULL, false); +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) + iwl_print_rx_config_cmd(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); +#endif + + iwlagn_fw_error(priv, false); +} + static int iwl_apm_stop_master(struct iwl_priv *priv) { int ret = 0; /* stop device's busmaster DMA activity */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(bus(priv), CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, + ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (ret) IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); @@ -924,13 +961,13 @@ void iwl_apm_stop(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); + clear_bit(STATUS_DEVICE_ENABLED, &priv->status); /* Stop device's DMA activity */ iwl_apm_stop_master(priv); /* Reset the entire device */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -938,7 +975,7 @@ void iwl_apm_stop(struct iwl_priv *priv) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } @@ -958,45 +995,45 @@ int iwl_apm_init(struct iwl_priv *priv) */ /* Disable L0S exit timer (platform NMI Work/Around) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); /* * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); bus_apm_config(priv->bus); /* Configure analog phase-lock-loop before activating to D0A */ if (priv->cfg->base_params->pll_cfg_val) - iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG, + iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->base_params->pll_cfg_val); /* * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. */ - iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* * Wait for clock stabilization; once stabilized, access to * device-internal resources is supported, e.g. iwl_write_prph() * and accesses to uCode SRAM. */ - ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { @@ -1011,14 +1048,14 @@ int iwl_apm_init(struct iwl_priv *priv) * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ - iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG, + iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); + set_bit(STATUS_DEVICE_ENABLED, &priv->status); out: return ret; @@ -1032,7 +1069,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) bool defer; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->tx_power_user_lmt == tx_power && !force) return 0; @@ -1052,7 +1089,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete and commit_rxon use tx_power_next value, @@ -1060,7 +1097,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) priv->tx_power_next = tx_power; /* do not set tx power when scanning or channel changing */ - defer = test_bit(STATUS_SCANNING, &priv->shrd->status) || + defer = test_bit(STATUS_SCANNING, &priv->status) || memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); if (defer && !force) { IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); @@ -1098,7 +1135,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -1111,17 +1148,22 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); } +void iwl_clear_isr_stats(struct iwl_priv *priv) +{ + memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); +} + int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -1132,7 +1174,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, IWL_DEBUG_MAC80211(priv, "enter\n"); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -1144,7 +1186,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, q = AC_NUM - 1 - queue; - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* * MULTI-FIXME @@ -1162,7 +1204,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; @@ -1190,7 +1232,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; int err; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* * This variable will be correct only when there's just @@ -1234,11 +1276,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cancel_delayed_work_sync(&priv->hw_roc_disable_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Try to add interface when device not ready\n"); err = -EINVAL; goto out; @@ -1281,7 +1323,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1293,7 +1335,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv, { struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); @@ -1325,14 +1367,14 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); WARN_ON(ctx->vif != vif); ctx->vif = NULL; iwl_teardown_interface(priv, vif, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1356,7 +1398,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) { u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) { + if (iwl_debug_level & IWL_DL_TX) { if (!priv->tx_traffic) { priv->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1364,7 +1406,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) return -ENOMEM; } } - if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) { + if (iwl_debug_level & IWL_DL_RX) { if (!priv->rx_traffic) { priv->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1391,7 +1433,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX))) + if (likely(!(iwl_debug_level & IWL_DL_TX))) return; if (!priv->tx_traffic) @@ -1415,7 +1457,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX))) + if (likely(!(iwl_debug_level & IWL_DL_RX))) return; if (!priv->rx_traffic) @@ -1572,7 +1614,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) static void iwl_force_rf_reset(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!iwl_is_any_associated(priv)) { @@ -1597,7 +1639,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) { struct iwl_force_reset *force_reset; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; if (mode >= IWL_MAX_FORCE_RESET) { @@ -1656,9 +1698,9 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, newtype = ieee80211_iftype_p2p(newtype, newp2p); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) { + if (!ctx->vif || !iwl_is_ready_rf(priv)) { /* * Huh? But wait ... this can maybe happen when * we're in the middle of a firmware restart! @@ -1720,16 +1762,36 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = 0; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return err; } -static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq) +/* + * On every watchdog tick we check (latest) time stamp. If it does not + * change during timeout period and queue is not empty we reset firmware. + */ +static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) { - if (iwl_trans_check_stuck_queue(trans(priv), txq)) { - int ret = iwl_force_reset(priv, IWL_FW_RESET, false); + struct iwl_tx_queue *txq = &priv->txq[cnt]; + struct iwl_queue *q = &txq->q; + unsigned long timeout; + int ret; + + if (q->read_ptr == q->write_ptr) { + txq->time_stamp = jiffies; + return 0; + } + + timeout = txq->time_stamp + + msecs_to_jiffies(priv->cfg->base_params->wd_timeout); + + if (time_after(jiffies, timeout)) { + IWL_ERR(priv, "Queue %d stuck for %u ms.\n", + q->id, priv->cfg->base_params->wd_timeout); + ret = iwl_force_reset(priv, IWL_FW_RESET, false); return (ret == -EAGAIN) ? 0 : 1; } + return 0; } @@ -1749,7 +1811,7 @@ void iwl_bg_watchdog(unsigned long data) int cnt; unsigned long timeout; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; timeout = priv->cfg->base_params->wd_timeout; @@ -1757,14 +1819,14 @@ void iwl_bg_watchdog(unsigned long data) return; /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) + if (iwl_check_stuck_queue(priv, priv->cmd_queue)) return; /* monitor and check for other stuck queues */ if (iwl_is_any_associated(priv)) { - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { /* skip as we already checked the command queue */ - if (cnt == priv->shrd->cmd_queue) + if (cnt == priv->cmd_queue) continue; if (iwl_check_stuck_queue(priv, cnt)) return; @@ -1803,12 +1865,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) quot = (usec / interval) & (iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits) >> - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits) >> + priv->hw_params.beacon_time_tsf_bits); rem = (usec % interval) & iwl_beacon_time_mask_low(priv, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); - return (quot << hw_params(priv).beacon_time_tsf_bits) + rem; + return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; } /* base is usually what we get from ucode with each received frame, @@ -1818,61 +1880,64 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval) { u32 base_low = base & iwl_beacon_time_mask_low(priv, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); u32 addon_low = addon & iwl_beacon_time_mask_low(priv, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); u32 interval = beacon_interval * TIME_UNIT; u32 res = (base & iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits)) + + priv->hw_params.beacon_time_tsf_bits)) + (addon & iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits)); + priv->hw_params.beacon_time_tsf_bits)); if (base_low > addon_low) res += base_low - addon_low; else if (base_low < addon_low) { res += interval + base_low - addon_low; - res += (1 << hw_params(priv).beacon_time_tsf_bits); + res += (1 << priv->hw_params.beacon_time_tsf_bits); } else - res += (1 << hw_params(priv).beacon_time_tsf_bits); + res += (1 << priv->hw_params.beacon_time_tsf_bits); return cpu_to_le32(res); } -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid) -{ - struct ieee80211_vif *vif; - u8 *addr = priv->stations[sta_id].sta.sta.addr; +#ifdef CONFIG_PM - if (ctx == NUM_IWL_RXON_CTX) - ctx = priv->stations[sta_id].ctxid; - vif = priv->contexts[ctx].vif; +int iwl_suspend(struct iwl_priv *priv) +{ + /* + * This function is called when system goes into suspend state + * mac80211 will call iwl_mac_stop() from the mac80211 suspend function + * first but since iwl_mac_stop() has no knowledge of who the caller is, + * it will not call apm_ops.stop() to stop the DMA operation. + * Calling apm_ops.stop here to make sure we stop the DMA. + * + * But of course ... if we have configured WoWLAN then we did other + * things already :-) + */ + if (!priv->wowlan) + iwl_apm_stop(priv); - ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); + return 0; } -void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid) +int iwl_resume(struct iwl_priv *priv) { - struct ieee80211_vif *vif; - u8 *addr = priv->stations[sta_id].sta.sta.addr; + bool hw_rfkill = false; - if (ctx == NUM_IWL_RXON_CTX) - ctx = priv->stations[sta_id].ctxid; - vif = priv->contexts[ctx].vif; + iwl_enable_interrupts(priv); - ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); -} + if (!(iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + hw_rfkill = true; -void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state) -{ - wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); -} + if (hw_rfkill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); -void iwl_nic_config(struct iwl_priv *priv) -{ - priv->cfg->lib->nic_config(priv); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill); + return 0; } + +#endif /* CONFIG_PM */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 56b554c43fde..42bcb469d32c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -71,8 +71,15 @@ struct iwl_host_cmd; struct iwl_cmd; + +#define IWLWIFI_VERSION "in-tree:" +#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_AUTHOR "" + #define TIME_UNIT 1024 +#define IWL_CMD(x) case x: return #x + struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -94,6 +101,23 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; +struct iwl_mod_params { + int sw_crypto; /* def: 0 = using hardware encryption */ + int num_of_queues; /* def: HW dependent */ + int disable_11n; /* def: 0 = 11n capabilities enabled */ + int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ + int antenna; /* def: 0 = both antennas (use diversity) */ + int restart_fw; /* def: 1 = restart firmware */ + bool plcp_check; /* def: true = enable plcp health check */ + bool ack_check; /* def: false = disable ack health check */ + bool wd_disable; /* def: false = enable stuck queue check */ + bool bt_coex_active; /* def: true = enable bt coex */ + int led_mode; /* def: 0 = system default */ + bool no_sleep_autoadjust; /* def: true = disable autoadjust */ + bool power_save; /* def: false = disable power save */ + int power_level; /* def: 1 = power level */ +}; + /* * @max_ll_items: max number of OTP blocks * @shadow_ram_support: shadow support for OTP memory @@ -198,7 +222,16 @@ struct iwl_ht_params { * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. + * it has a supported API version. The firmware's API version will be + * stored in @iwl_priv, enabling the driver to make runtime changes based + * on firmware version used. + * + * For example, + * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { + * Driver interacts with Firmware API version >= 2. + * } else { + * Driver interacts with Firmware API version 1. + * } * * The ideal usage of this infrastructure is to treat a new ucode API * release as a new hardware revision. @@ -259,6 +292,7 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, void iwl_connection_init_rx_config(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_set_rate(struct iwl_priv *priv); +void iwl_irq_handle_error(struct iwl_priv *priv); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, @@ -269,6 +303,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); +void iwl_reset_traffic_log(struct iwl_priv *priv); void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, u16 length, struct ieee80211_hdr *header); void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, @@ -357,21 +392,117 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, * S e n d i n g H o s t C o m m a n d s * *****************************************************/ +const char *get_cmd_string(u8 cmd); void iwl_bg_watchdog(unsigned long data); u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, u32 addon, u32 beacon_interval); +#ifdef CONFIG_PM +int iwl_suspend(struct iwl_priv *priv); +int iwl_resume(struct iwl_priv *priv); +#endif /* !CONFIG_PM */ + +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); +void __devexit iwl_remove(struct iwl_priv * priv); + +/***************************************************** +* Error Handling Debugging +******************************************************/ +void iwl_dump_nic_error_log(struct iwl_priv *priv); +int iwl_dump_nic_event_log(struct iwl_priv *priv, + bool full_log, char **buf, bool display); +void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); +#ifdef CONFIG_IWLWIFI_DEBUG +void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); +#else +static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ +} +#endif + +void iwl_clear_isr_stats(struct iwl_priv *priv); /***************************************************** * GEOS ******************************************************/ -int iwl_init_geos(struct iwl_priv *priv); -void iwl_free_geos(struct iwl_priv *priv); +int iwlcore_init_geos(struct iwl_priv *priv); +void iwlcore_free_geos(struct iwl_priv *priv); + +/*************** DRIVER STATUS FUNCTIONS *****/ + +#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ +/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_CT_KILL 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_DEVICE_ENABLED 18 +#define STATUS_CHANNEL_SWITCH_PENDING 19 + + +static inline int iwl_is_ready(struct iwl_priv *priv) +{ + /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are + * set but EXIT_PENDING is not */ + return test_bit(STATUS_READY, &priv->status) && + test_bit(STATUS_GEO_CONFIGURED, &priv->status) && + !test_bit(STATUS_EXIT_PENDING, &priv->status); +} + +static inline int iwl_is_alive(struct iwl_priv *priv) +{ + return test_bit(STATUS_ALIVE, &priv->status); +} + +static inline int iwl_is_init(struct iwl_priv *priv) +{ + return test_bit(STATUS_INIT, &priv->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + +static inline int iwl_is_rfkill(struct iwl_priv *priv) +{ + return iwl_is_rfkill_hw(priv); +} + +static inline int iwl_is_ctkill(struct iwl_priv *priv) +{ + return test_bit(STATUS_CT_KILL, &priv->status); +} + +static inline int iwl_is_ready_rf(struct iwl_priv *priv) +{ + + if (iwl_is_rfkill(priv)) + return 0; + + return iwl_is_ready(priv); +} extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); +void iwl_apm_stop(struct iwl_priv *priv); +int iwl_apm_init(struct iwl_priv *priv); int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -389,4 +520,7 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) extern bool bt_siso_mode; + +void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); + #endif /* __iwl_core_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h index b9f3267e720c..d6dbb0423045 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -439,22 +439,4 @@ */ #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) -/********************************************************** - * CSR values - **********************************************************/ - /* - * host interrupt timeout value - * used with setting interrupt coalescing timer - * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit - * - * default interrupt coalescing timer is 64 x 32 = 2048 usecs - * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs - */ -#define IWL_HOST_INT_TIMEOUT_MAX (0xFF) -#define IWL_HOST_INT_TIMEOUT_DEF (0x40) -#define IWL_HOST_INT_TIMEOUT_MIN (0x0) -#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) -#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) -#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) - #endif /* !__iwl_csr_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h index 7014f4124484..f9a407e40aff 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -29,51 +29,50 @@ #ifndef __iwl_debug_h__ #define __iwl_debug_h__ -#include "iwl-bus.h" -#include "iwl-shared.h" - struct iwl_priv; +extern u32 iwl_debug_level; -/*No matter what is m (priv, bus, trans), this will work */ -#define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a) -#define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a) -#define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a) -#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a) +#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) +#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) -#define iwl_print_hex_error(m, p, len) \ +#define iwl_print_hex_error(priv, p, len) \ do { \ print_hex_dump(KERN_ERR, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(m, level, fmt, args...) \ +#define IWL_DEBUG(__priv, level, fmt, args...) \ do { \ - if (iwl_get_debug_level((m)->shrd) & (level)) \ - dev_printk(KERN_ERR, bus(m)->dev, \ + if (iwl_get_debug_level(__priv) & (level)) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ do { \ - if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\ - dev_printk(KERN_ERR, bus(m)->dev, \ + if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define iwl_print_hex_dump(m, level, p, len) \ +#define iwl_print_hex_dump(priv, level, p, len) \ do { \ - if (iwl_get_debug_level((m)->shrd) & level) \ + if (iwl_get_debug_level(priv) & level) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #else -#define IWL_DEBUG(m, level, fmt, args...) -#define IWL_DEBUG_LIMIT(m, level, fmt, args...) -#define iwl_print_hex_dump(m, level, p, len) +#define IWL_DEBUG(__priv, level, fmt, args...) +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) +static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, + const void *p, u32 len) +{} #endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -167,7 +166,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a) #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d0c63cfee15c..ec1485b2d3fe 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -254,7 +254,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, sram = priv->dbgfs_sram_offset & ~0x3; /* read the first u32 from sram */ - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(priv, sram); for (; len; len--) { /* put the address at the start of every line */ @@ -273,7 +273,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, if (++offset == 4) { sram += 4; offset = 0; - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(priv, sram); } /* put in extra spaces and split lines for human readability */ @@ -340,8 +340,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = file->private_data; struct iwl_station_entry *station; - struct iwl_tid_data *tid_data; - int max_sta = hw_params(priv).max_stations; + int max_sta = priv->hw_params.max_stations; char *buf; int i, j, pos = 0; ssize_t ret; @@ -364,18 +363,22 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, i, station->sta.sta.addr, station->sta.station_flags_msk); pos += scnprintf(buf + pos, bufsz - pos, - "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n"); + "TID\tseq_num\ttxq_id\tframes\ttfds\t"); + pos += scnprintf(buf + pos, bufsz - pos, + "start_idx\tbitmap\t\t\trate_n_flags\n"); - for (j = 0; j < IWL_MAX_TID_COUNT; j++) { - tid_data = &priv->shrd->tid_data[i][j]; + for (j = 0; j < MAX_TID_COUNT; j++) { pos += scnprintf(buf + pos, bufsz - pos, - "%d:\t%#x\t%#x\t%u\t%#x", - j, tid_data->seq_number, - tid_data->agg.txq_id, - tid_data->tfds_in_queue, - tid_data->agg.rate_n_flags); - - if (tid_data->agg.wait_for_ba) + "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", + j, station->tid[j].seq_number, + station->tid[j].agg.txq_id, + station->tid[j].agg.frame_count, + station->tid[j].tfds_in_queue, + station->tid[j].agg.start_idx, + station->tid[j].agg.bitmap, + station->tid[j].agg.rate_n_flags); + + if (station->tid[j].agg.wait_for_ba) pos += scnprintf(buf + pos, bufsz - pos, " - waitforba"); pos += scnprintf(buf + pos, bufsz - pos, "\n"); @@ -439,6 +442,46 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, return ret; } +static ssize_t iwl_dbgfs_log_event_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -ENOMEM; + + ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + } + return ret; +} + +static ssize_t iwl_dbgfs_log_event_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + u32 event_log_flag; + char buf[8]; + int buf_size; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &event_log_flag) != 1) + return -EFAULT; + if (event_log_flag == 1) + iwl_dump_nic_event_log(priv, true, NULL, false); + + return count; +} + + + static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -449,7 +492,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, char *buf; ssize_t ret; - if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)) + if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -519,46 +562,45 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, const size_t bufsz = sizeof(buf); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", - test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); + test_bit(STATUS_HCMD_ACTIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", - test_bit(STATUS_INT_ENABLED, &priv->shrd->status)); + test_bit(STATUS_INT_ENABLED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", - test_bit(STATUS_CT_KILL, &priv->shrd->status)); + test_bit(STATUS_CT_KILL, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", - test_bit(STATUS_INIT, &priv->shrd->status)); + test_bit(STATUS_INIT, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", - test_bit(STATUS_ALIVE, &priv->shrd->status)); + test_bit(STATUS_ALIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", - test_bit(STATUS_READY, &priv->shrd->status)); + test_bit(STATUS_READY, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", - test_bit(STATUS_TEMPERATURE, &priv->shrd->status)); + test_bit(STATUS_TEMPERATURE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)); + test_bit(STATUS_GEO_CONFIGURED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)); + test_bit(STATUS_EXIT_PENDING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", - test_bit(STATUS_STATISTICS, &priv->shrd->status)); + test_bit(STATUS_STATISTICS, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", - test_bit(STATUS_SCANNING, &priv->shrd->status)); + test_bit(STATUS_SCANNING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", - test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)); + test_bit(STATUS_SCAN_ABORTING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", - test_bit(STATUS_SCAN_HW, &priv->shrd->status)); + test_bit(STATUS_SCAN_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", - test_bit(STATUS_POWER_PMI, &priv->shrd->status)); + test_bit(STATUS_POWER_PMI, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", - test_bit(STATUS_FW_ERROR, &priv->shrd->status)); + test_bit(STATUS_FW_ERROR, &priv->status)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, +static ssize_t iwl_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - int pos = 0; int cnt = 0; char *buf; @@ -571,25 +613,61 @@ static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, return -ENOMEM; } + pos += scnprintf(buf + pos, bufsz - pos, + "Interrupt Statistics Report:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", + priv->isr_stats.hw); + pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", + priv->isr_stats.sw); + if (priv->isr_stats.sw || priv->isr_stats.hw) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tLast Restarting Code: 0x%X\n", + priv->isr_stats.err_code); + } +#ifdef CONFIG_IWLWIFI_DEBUG + pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", + priv->isr_stats.sch); + pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", + priv->isr_stats.alive); +#endif + pos += scnprintf(buf + pos, bufsz - pos, + "HW RF KILL switch toggled:\t %u\n", + priv->isr_stats.rfkill); + + pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", + priv->isr_stats.ctkill); + + pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", + priv->isr_stats.wakeup); + + pos += scnprintf(buf + pos, bufsz - pos, + "Rx command responses:\t\t %u\n", + priv->isr_stats.rx); for (cnt = 0; cnt < REPLY_MAX; cnt++) { - if (priv->rx_handlers_stats[cnt] > 0) + if (priv->isr_stats.rx_handlers[cnt] > 0) pos += scnprintf(buf + pos, bufsz - pos, "\tRx handler[%36s]:\t\t %u\n", get_cmd_string(cnt), - priv->rx_handlers_stats[cnt]); + priv->isr_stats.rx_handlers[cnt]); } + pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", + priv->isr_stats.tx); + + pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", + priv->isr_stats.unhandled); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; } -static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, +static ssize_t iwl_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - char buf[8]; int buf_size; u32 reset_flag; @@ -601,8 +679,7 @@ static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, if (sscanf(buf, "%x", &reset_flag) != 1) return -EFAULT; if (reset_flag == 0) - memset(&priv->rx_handlers_stats[0], 0, - sizeof(priv->rx_handlers_stats)); + iwl_clear_isr_stats(priv); return count; } @@ -737,14 +814,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) return -EINVAL; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EAGAIN; priv->power_data.debug_sleep_level_override = value; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_power_update_mode(priv, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return count; } @@ -793,11 +870,12 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_FILE_OPS(wowlan_sram); +DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); -DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers); +DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); @@ -811,23 +889,36 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, struct iwl_priv *priv = file->private_data; int pos = 0, ofs = 0; int cnt = 0, entry; - + struct iwl_tx_queue *txq; + struct iwl_queue *q; + struct iwl_rx_queue *rxq = &priv->rxq; char *buf; int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (hw_params(priv).max_txq_num * 32 * 8) + 400; + (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; const u8 *ptr; ssize_t ret; + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { IWL_ERR(priv, "Can not allocate buffer\n"); return -ENOMEM; } - if (priv->tx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { + pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "q[%d]: read_ptr: %u, write_ptr: %u\n", + cnt, q->read_ptr, q->write_ptr); + } + if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { ptr = priv->tx_traffic; pos += scnprintf(buf + pos, bufsz - pos, - "Tx Traffic idx: %u\n", priv->tx_traffic_idx); + "Tx Traffic idx: %u\n", priv->tx_traffic_idx); for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; entry++, ofs += 16) { @@ -842,11 +933,15 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, } } - if (priv->rx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { + pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "read: %u, write: %u\n", + rxq->read, rxq->write); + + if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { ptr = priv->rx_traffic; pos += scnprintf(buf + pos, bufsz - pos, - "Rx Traffic idx: %u\n", priv->rx_traffic_idx); + "Rx Traffic idx: %u\n", priv->rx_traffic_idx); for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; entry++, ofs += 16) { @@ -887,6 +982,76 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + char *buf; + int pos = 0; + int cnt; + int ret; + const size_t bufsz = sizeof(char) * 64 * + priv->cfg->base_params->num_of_queues; + + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "hwq %.2d: read=%u write=%u stop=%d" + " swq_id=%#.2x (ac %d/hwq %d)\n", + cnt, q->read_ptr, q->write_ptr, + !!test_bit(cnt, priv->queue_stopped), + txq->swq_id, txq->swq_id & 3, + (txq->swq_id >> 2) & 0x1f); + if (cnt >= 4) + continue; + /* for the ACs, display the stop count too */ + pos += scnprintf(buf + pos, bufsz - pos, + " stop-count: %d\n", + atomic_read(&priv->queue_stop_count[cnt])); + } + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + struct iwl_rx_queue *rxq = &priv->rxq; + char buf[256]; + int pos = 0; + const size_t bufsz = sizeof(buf); + + pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", + rxq->read); + pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", + rxq->write); + pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", + rxq->free_count); + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", + le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "closed_rb_num: Not Allocated\n"); + } + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + static const char *fmt_value = " %-30s %10u\n"; static const char *fmt_hex = " %-30s 0x%02X\n"; static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; @@ -931,7 +1096,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, struct statistics_rx_non_phy *delta_general, *max_general; struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1357,7 +1522,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, ssize_t ret; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1551,7 +1716,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1664,16 +1829,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, ssize_t ret; struct statistics_bt_activity *bt, *accum_bt; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; if (!priv->bt_enable_flag) return -EINVAL; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) { IWL_ERR(priv, @@ -1752,7 +1917,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; ssize_t ret; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -2034,7 +2199,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, const size_t bufsz = sizeof(buf); u32 pwrsave_status; - pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) & + pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); @@ -2064,9 +2229,30 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return -EFAULT; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_send_statistics_request(priv, CMD_SYNC, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); + + return count; +} + +static ssize_t iwl_dbgfs_csr_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int csr; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &csr) != 1) + return -EFAULT; + + iwl_dump_csr(priv); return count; } @@ -2147,6 +2333,25 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } +static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -EFAULT; + + ret = pos = iwl_dump_fh(priv, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); + } + + return ret; +} + static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -2299,7 +2504,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, if (sscanf(buf, "%d", &flush) != 1) return -EINVAL; - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -EFAULT; iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); @@ -2424,6 +2629,8 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); +DEBUGFS_READ_FILE_OPS(rx_queue); +DEBUGFS_READ_FILE_OPS(tx_queue); DEBUGFS_READ_FILE_OPS(ucode_rx_stats); DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats); @@ -2432,7 +2639,9 @@ DEBUGFS_READ_FILE_OPS(chain_noise); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); +DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); +DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(force_reset); @@ -2473,10 +2682,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); @@ -2485,9 +2695,13 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); @@ -2511,9 +2725,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); - - if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) - goto err; return 0; err: diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index 8438a33e17ee..dd34c7c502fa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -32,15 +32,16 @@ #define __iwl_dev_h__ #include +#include /* for struct pci_device_id */ #include #include #include -#include #include #include "iwl-eeprom.h" #include "iwl-csr.h" #include "iwl-prph.h" +#include "iwl-fh.h" #include "iwl-debug.h" #include "iwl-agn-hw.h" #include "iwl-led.h" @@ -49,7 +50,8 @@ #include "iwl-agn-tt.h" #include "iwl-bus.h" #include "iwl-trans.h" -#include "iwl-shared.h" + +#define DRV_NAME "iwlagn" struct iwl_tx_queue; @@ -88,6 +90,109 @@ struct iwl_tx_queue; #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U +struct iwl_rx_mem_buffer { + dma_addr_t page_dma; + struct page *page; + struct list_head list; +}; + +#define rxb_addr(r) page_address(r->page) + +/* defined below */ +struct iwl_device_cmd; + +struct iwl_cmd_meta { + /* only for SYNC commands, iff the reply skb is wanted */ + struct iwl_host_cmd *source; + /* + * only for ASYNC commands + * (which is somewhat stupid -- look at iwl-sta.c for instance + * which duplicates a bunch of code because the callback isn't + * invoked for SYNC commands, if it were and its result passed + * through it would be simpler...) + */ + void (*callback)(struct iwl_priv *priv, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt); + + u32 flags; + + DEFINE_DMA_UNMAP_ADDR(mapping); + DEFINE_DMA_UNMAP_LEN(len); +}; + +/* + * Generic queue structure + * + * Contains common data for Rx and Tx queues. + * + * Note the difference between n_bd and n_window: the hardware + * always assumes 256 descriptors, so n_bd is always 256 (unless + * there might be HW changes in the future). For the normal TX + * queues, n_window, which is the size of the software queue data + * is also 256; however, for the command queue, n_window is only + * 32 since we don't need so many commands pending. Since the HW + * still uses 256 BDs for DMA though, n_bd stays 256. As a result, + * the software buffers (in the variables @meta, @txb in struct + * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds + * in the same struct) have 256. + * This means that we end up with the following: + * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | + * SW entries: | 0 | ... | 31 | + * where N is a number between 0 and 7. This means that the SW + * data is a window overlayed over the HW queue. + */ +struct iwl_queue { + int n_bd; /* number of BDs in this queue */ + int write_ptr; /* 1-st empty entry (index) host_w*/ + int read_ptr; /* last used entry (index) host_r*/ + /* use for monitoring and recovering the stuck queue */ + dma_addr_t dma_addr; /* physical addr for BD's */ + int n_window; /* safe queue window */ + u32 id; + int low_mark; /* low watermark, resume queue if free + * space more than this */ + int high_mark; /* high watermark, stop queue if free + * space less than this */ +}; + +/* One for each TFD */ +struct iwl_tx_info { + struct sk_buff *skb; + struct iwl_rxon_context *ctx; +}; + +/** + * struct iwl_tx_queue - Tx Queue for DMA + * @q: generic Rx/Tx queue descriptor + * @bd: base of circular buffer of TFDs + * @cmd: array of command/TX buffer pointers + * @meta: array of meta data for each command/tx buffer + * @dma_addr_cmd: physical address of cmd/tx buffer array + * @txb: array of per-TFD driver data + * @time_stamp: time (in jiffies) of last read_ptr change + * @need_update: indicates need to update read/write index + * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled + * + * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame + * descriptors) and required locking structures. + */ +#define TFD_TX_CMD_SLOTS 256 +#define TFD_CMD_SLOTS 32 + +struct iwl_tx_queue { + struct iwl_queue q; + struct iwl_tfd *tfds; + struct iwl_device_cmd **cmd; + struct iwl_cmd_meta *meta; + struct iwl_tx_info *txb; + unsigned long time_stamp; + u8 need_update; + u8 sched_retry; + u8 active; + u8 swq_id; +}; + #define IWL_NUM_SCAN_RATES (2) /* @@ -117,6 +222,21 @@ struct iwl_channel_info { u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ }; +#define IWL_TX_FIFO_BK 0 /* shared */ +#define IWL_TX_FIFO_BE 1 +#define IWL_TX_FIFO_VI 2 /* shared */ +#define IWL_TX_FIFO_VO 3 +#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK +#define IWL_TX_FIFO_BE_IPAN 4 +#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI +#define IWL_TX_FIFO_VO_IPAN 5 +/* re-uses the VO FIFO, uCode will properly flush/schedule */ +#define IWL_TX_FIFO_AUX 5 +#define IWL_TX_FIFO_UNUSED -1 + +/* AUX (TX during scan dwell) queue */ +#define IWL_AUX_QUEUE 10 + /* * Minimum number of queues. MAX_NUM is defined in hw specific files. * Set the minimum to accommodate @@ -134,20 +254,161 @@ struct iwl_channel_info { #define IWL_DEFAULT_CMD_QUEUE_NUM 4 #define IWL_IPAN_CMD_QUEUE_NUM 9 +/* + * This queue number is required for proper operation + * because the ucode will stop/start the scheduler as + * required. + */ +#define IWL_IPAN_MCAST_QUEUE 8 + #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) + +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) + +enum { + CMD_SYNC = 0, + CMD_ASYNC = BIT(0), + CMD_WANT_SKB = BIT(1), + CMD_ON_DEMAND = BIT(2), +}; + +#define DEF_CMD_PAYLOAD_SIZE 320 + +/** + * struct iwl_device_cmd + * + * For allocation of the command and tx queues, this establishes the overall + * size of the largest command we send to uCode, except for commands that + * aren't fully copied and use other TFD space. + */ +struct iwl_device_cmd { + struct iwl_cmd_header hdr; /* uCode API */ + union { + u32 flags; + u8 val8; + u16 val16; + u32 val32; + struct iwl_tx_cmd tx; + struct iwl6000_channel_switch_cmd chswitch; + u8 payload[DEF_CMD_PAYLOAD_SIZE]; + } __packed cmd; +} __packed; + +#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) + +#define IWL_MAX_CMD_TFDS 2 + +enum iwl_hcmd_dataflag { + IWL_HCMD_DFL_NOCOPY = BIT(0), +}; + +/** + * struct iwl_host_cmd - Host command to the uCode + * @data: array of chunks that composes the data of the host command + * @reply_page: pointer to the page that holds the response to the host command + * @callback: + * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC + * @len: array of the lenths of the chunks in data + * @dataflags: + * @id: id of the host command + */ +struct iwl_host_cmd { + const void *data[IWL_MAX_CMD_TFDS]; + unsigned long reply_page; + void (*callback)(struct iwl_priv *priv, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt); + u32 flags; + u16 len[IWL_MAX_CMD_TFDS]; + u8 dataflags[IWL_MAX_CMD_TFDS]; + u8 id; +}; + #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 +/** + * struct iwl_rx_queue - Rx queue + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) + * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @read: Shared index to newest available Rx buffer + * @write: Shared index to oldest written Rx packet + * @free_count: Number of pre-allocated buffers in rx_free + * @rx_free: list of free SKBs for use + * @rx_used: List of Rx buffers with no SKB + * @need_update: flag to indicate we need to update read/write index + * @rb_stts: driver's pointer to receive buffer status + * @rb_stts_dma: bus address of receive buffer status + * + * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers + */ +struct iwl_rx_queue { + __le32 *bd; + dma_addr_t bd_dma; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; + u32 read; + u32 write; + u32 free_count; + u32 write_actual; + struct list_head rx_free; + struct list_head rx_used; + int need_update; + struct iwl_rb_status *rb_stts; + dma_addr_t rb_stts_dma; + spinlock_t lock; +}; + #define IWL_SUPPORTED_RATES_IE_LEN 8 +#define MAX_TID_COUNT 9 + #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 +/** + * struct iwl_ht_agg -- aggregation status while waiting for block-ack + * @txq_id: Tx queue used for Tx attempt + * @frame_count: # frames attempted by Tx command + * @wait_for_ba: Expect block-ack before next Tx reply + * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window + * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window + * @bitmap1: High order, one bit for each frame pending ACK in Tx window + * @rate_n_flags: Rate at which Tx was attempted + * + * If REPLY_TX indicates that aggregation was attempted, driver must wait + * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info + * until block ack arrives. + */ +struct iwl_ht_agg { + u16 txq_id; + u16 frame_count; + u16 wait_for_ba; + u16 start_idx; + u64 bitmap; + u32 rate_n_flags; +#define IWL_AGG_OFF 0 +#define IWL_AGG_ON 1 +#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 +#define IWL_EMPTYING_HW_QUEUE_DELBA 3 + u8 state; + u8 tx_fifo; +}; + + +struct iwl_tid_data { + u16 seq_number; /* agn only */ + u16 tfds_in_queue; + struct iwl_ht_agg agg; +}; + union iwl_ht_rate_supp { u16 rates; struct { @@ -198,6 +459,7 @@ struct iwl_qos_info { */ struct iwl_station_entry { struct iwl_addsta_cmd sta; + struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used, ctxid; struct iwl_link_quality_cmd *lq; }; @@ -385,6 +647,54 @@ struct iwl_sensitivity_ranges { #define CELSIUS_TO_KELVIN(x) ((x)+273) +/** + * struct iwl_hw_params + * @max_txq_num: Max # Tx queues supported + * @scd_bc_tbls_size: size of scheduler byte count tables + * @tfd_size: TFD size + * @tx/rx_chains_num: Number of TX/RX chains + * @valid_tx/rx_ant: usable antennas + * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) + * @max_rxq_log: Log-base-2 of max_rxq_size + * @rx_page_order: Rx buffer page order + * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR + * @max_stations: + * @ht40_channel: is 40MHz width possible in band 2.4 + * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) + * @sw_crypto: 0 for hw, 1 for sw + * @max_xxx_size: for ucode uses + * @ct_kill_threshold: temperature threshold + * @beacon_time_tsf_bits: number of valid tsf bits for beacon time + * @calib_init_cfg: setup initial calibrations for the hw + * @calib_rt_cfg: setup runtime calibrations for the hw + * @struct iwl_sensitivity_ranges: range of sensitivity values + */ +struct iwl_hw_params { + u8 max_txq_num; + u16 scd_bc_tbls_size; + u32 tfd_size; + u8 tx_chains_num; + u8 rx_chains_num; + u8 valid_tx_ant; + u8 valid_rx_ant; + u16 max_rxq_size; + u16 max_rxq_log; + u32 rx_page_order; + u8 max_stations; + u8 ht40_channel; + u8 max_beacon_itrvl; /* in 1024 ms */ + u32 max_inst_size; + u32 max_data_size; + u32 ct_kill_threshold; /* value in hw-dependent units */ + u32 ct_kill_exit_threshold; /* value in hw-dependent units */ + /* for 1000, 6000 series and up */ + u16 beacon_time_tsf_bits; + u32 calib_init_cfg; + u32 calib_rt_cfg; + const struct iwl_sensitivity_ranges *sens; +}; + + /****************************************************************************** * * Functions implemented in core module which are forward declared here @@ -400,12 +710,35 @@ struct iwl_sensitivity_ranges { ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); extern const u8 iwl_bcast_addr[ETH_ALEN]; +extern int iwl_queue_space(const struct iwl_queue *q); +static inline int iwl_queue_used(const struct iwl_queue *q, int i) +{ + return q->write_ptr >= q->read_ptr ? + (i >= q->read_ptr && i < q->write_ptr) : + !(i < q->read_ptr && i >= q->write_ptr); +} + + +static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) +{ + return index & (q->n_window - 1); +} + + +struct iwl_dma_ptr { + dma_addr_t dma; + void *addr; + size_t size; +}; #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 #define IWL_OPERATION_MODE_MIXED 2 #define IWL_OPERATION_MODE_20MHZ 3 +#define IWL_TX_CRC_SIZE 4 +#define IWL_TX_DELIMITER_SIZE 4 + #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 /* Sensitivity and chain noise calibration */ @@ -529,6 +862,9 @@ struct iwl_chain_noise_data { #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ +#define IWL_TRAFFIC_ENTRIES (256) +#define IWL_TRAFFIC_ENTRY_SIZE (64) + enum { MEASUREMENT_READY = (1 << 0), MEASUREMENT_ACTIVE = (1 << 1), @@ -561,6 +897,22 @@ enum iwl_pa_type { IWL_PA_INTERNAL = 1, }; +/* interrupt statistics */ +struct isr_statistics { + u32 hw; + u32 sw; + u32 err_code; + u32 sch; + u32 alive; + u32 rfkill; + u32 ctkill; + u32 wakeup; + u32 rx; + u32 rx_handlers[REPLY_MAX]; + u32 tx; + u32 unhandled; +}; + /* reply_tx_statistics (for _agn devices) */ struct reply_tx_error_statistics { u32 pp_delay; @@ -669,6 +1021,21 @@ struct iwl_event_log { int wraps_more_count; }; +/* + * host interrupt timeout value + * used with setting interrupt coalescing timer + * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit + * + * default interrupt coalescing timer is 64 x 32 = 2048 usecs + * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs + */ +#define IWL_HOST_INT_TIMEOUT_MAX (0xFF) +#define IWL_HOST_INT_TIMEOUT_DEF (0x40) +#define IWL_HOST_INT_TIMEOUT_MIN (0x0) +#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) +#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) +#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) + /* * This is the threshold value of plcp error rate per 100mSecs. It is * used to set and check for the validity of plcp_delta. @@ -747,9 +1114,20 @@ struct iwl_notification_wait { bool triggered, aborted; }; +enum iwl_rxon_context_id { + IWL_RXON_CTX_BSS, + IWL_RXON_CTX_PAN, + + NUM_IWL_RXON_CTX +}; + struct iwl_rxon_context { struct ieee80211_vif *vif; + const u8 *ac_to_fifo; + const u8 *ac_to_queue; + u8 mcast_queue; + /* * We could use the vif to indicate active, but we * also need it to be active during disabling when @@ -797,9 +1175,6 @@ struct iwl_rxon_context { u8 extension_chan_offset; } ht; - u8 bssid[ETH_ALEN]; - bool preauth_bssid; - bool last_tx_rejected; }; @@ -828,17 +1203,16 @@ struct iwl_testmode_trace { }; #endif -struct iwl_priv { +/* uCode ownership */ +#define IWL_OWNERSHIP_DRIVER 0 +#define IWL_OWNERSHIP_TM 1 - /*data shared among all the driver's layers */ - struct iwl_shared _shrd; - struct iwl_shared *shrd; +struct iwl_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; - struct kmem_cache *tx_cmd_pool; struct iwl_cfg *cfg; enum ieee80211_band band; @@ -864,9 +1238,6 @@ struct iwl_priv { /* jiffies when last recovery from statistics was performed */ unsigned long rx_statistics_jiffies; - /*counters */ - u32 rx_handlers_stats[REPLY_MAX]; - /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; @@ -897,8 +1268,20 @@ struct iwl_priv { u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; - /*TODO: remove these pointers - use bus(priv) instead */ + /* spinlock */ + spinlock_t lock; /* protect general shared data */ + spinlock_t hcmd_lock; /* protect hcmd */ + spinlock_t reg_lock; /* protect hw register access */ + struct mutex mutex; + struct iwl_bus *bus; /* bus specific data */ + struct iwl_trans trans; + + /* microcode/device supports multiple contexts */ + u8 valid_contexts; + + /* command queue number */ + u8 cmd_queue; /* max number of station keys */ u8 sta_key_max_num; @@ -913,6 +1296,9 @@ struct iwl_priv { u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ + /* uCode owner: default: IWL_OWNERSHIP_DRIVER */ + u8 ucode_owner; + struct fw_img ucode_rt; struct fw_img ucode_init; struct fw_img ucode_wowlan; @@ -944,23 +1330,52 @@ struct iwl_priv { /* Rate scaling data */ u8 retry_rate; + wait_queue_head_t wait_command_queue; + int activity_timer_active; + /* Rx and Tx DMA processing queues */ + struct iwl_rx_queue rxq; + struct iwl_tx_queue *txq; + unsigned long txq_ctx_active_msk; + struct iwl_dma_ptr kw; /* keep warm address */ + struct iwl_dma_ptr scd_bc_tbls; + + u32 scd_base_addr; /* scheduler sram base address */ + + unsigned long status; + /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; struct traffic_stats rx_stats; + /* counts interrupts */ + struct isr_statistics isr_stats; + struct iwl_power_mgr power_data; struct iwl_tt_mgmt thermal_throttle; /* station table variables */ + + /* Note: if lock and sta_lock are needed, lock must be acquired first */ + spinlock_t sta_lock; int num_stations; struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; unsigned long ucode_key_table; + /* queue refcounts */ +#define IWL_MAX_HW_QUEUES 32 + unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; + /* for each AC */ + atomic_t queue_stop_count[4]; + /* Indication if ieee80211_ops->open has been called */ u8 is_open; + u8 mac80211_registered; + + bool wowlan; + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; @@ -996,6 +1411,14 @@ struct iwl_priv { } accum_stats, delta_stats, max_delta_stats; #endif + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; /* * reporting the number of tids has AGG on. 0 means * no AGGREGATION @@ -1052,8 +1475,15 @@ struct iwl_priv { struct iwl_rxon_context *cur_rssi_ctx; bool bt_is_sco; + struct iwl_hw_params hw_params; + + u32 inta_mask; + + struct workqueue_struct *workqueue; + struct work_struct restart; struct work_struct scan_completed; + struct work_struct rx_replenish; struct work_struct abort_scan; struct work_struct beacon_update; @@ -1069,6 +1499,8 @@ struct iwl_priv { struct work_struct bt_full_concurrency; struct work_struct bt_runtime_config; + struct tasklet_struct irq_tasklet; + struct delayed_work scan_check; /* TX Power */ @@ -1077,6 +1509,12 @@ struct iwl_priv { s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ s8 tx_power_next; + +#ifdef CONFIG_IWLWIFI_DEBUG + /* debugging info */ + u32 debug_level; /* per device debugging will override global + iwl_debug_level if set */ +#endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS /* debugfs */ u16 tx_traffic_idx; @@ -1114,7 +1552,47 @@ struct iwl_priv { bool have_rekey_data; }; /*iwl_priv */ -extern struct iwl_mod_params iwlagn_mod_params; +static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) +{ + set_bit(txq_id, &priv->txq_ctx_active_msk); +} + +static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) +{ + clear_bit(txq_id, &priv->txq_ctx_active_msk); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +/* + * iwl_get_debug_level: Return active debug level for device + * + * Using sysfs it is possible to set per device debug level. This debug + * level will be used if set, otherwise the global debug level which can be + * set via module parameter is used. + */ +static inline u32 iwl_get_debug_level(struct iwl_priv *priv) +{ + if (priv->debug_level) + return priv->debug_level; + else + return iwl_debug_level; +} +#else +static inline u32 iwl_get_debug_level(struct iwl_priv *priv) +{ + return iwl_debug_level; +} +#endif + + +static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, + int txq_id, int idx) +{ + if (priv->txq[txq_id].txb[idx].skb) + return (struct ieee80211_hdr *)priv->txq[txq_id]. + txb[idx].skb->data; + return NULL; +} static inline struct iwl_rxon_context * iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) @@ -1127,7 +1605,7 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) #define for_each_context(priv, ctx) \ for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \ ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ - if (priv->shrd->valid_contexts & BIT(ctx->ctxid)) + if (priv->valid_contexts & BIT(ctx->ctxid)) static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) { @@ -1181,4 +1659,13 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } +static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) +{ + __free_pages(page, priv->hw_params.rx_page_order); +} + +static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) +{ + free_pages(page, priv->hw_params.rx_page_order); +} #endif /* __iwl_dev_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 8a51c5ccda1e..2c84ba95afca 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -29,8 +29,6 @@ #include -struct iwl_priv; - #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 80ee65be9cd1..19d31a5e32e5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -155,11 +155,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl_poll_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); @@ -176,14 +176,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) { - iwl_clear_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); } static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { - u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; + u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; int ret = 0; IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); @@ -216,17 +216,17 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { - iwl_read32(bus(priv), CSR_OTP_GP_REG); + iwl_read32(priv, CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) - iwl_clear_bit(bus(priv), CSR_OTP_GP_REG, + iwl_clear_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); else - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) +static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) { u32 otpgp; int nvm_type; @@ -243,7 +243,7 @@ static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) nvm_type = NVM_DEVICE_TYPE_EEPROM; break; default: - otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) nvm_type = NVM_DEVICE_TYPE_OTP; else @@ -258,22 +258,22 @@ static int iwl_init_otp_access(struct iwl_priv *priv) int ret; /* Enable 40MHz radio clock */ - iwl_write32(bus(priv), CSR_GP_CNTRL, - iwl_read32(bus(priv), CSR_GP_CNTRL) | + iwl_write32(priv, CSR_GP_CNTRL, + iwl_read32(priv, CSR_GP_CNTRL) | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ - ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { - iwl_set_bits_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl_clear_bits_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); /* @@ -281,7 +281,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) * this is only applicable for HW with OTP shadow RAM */ if (priv->cfg->base_params->shadow_ram_support) - iwl_set_bit(bus(priv), CSR_DBG_LINK_PWR_MGMT_REG, + iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, CSR_RESET_LINK_PWR_MGMT_DISABLED); } return ret; @@ -293,9 +293,9 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - iwl_write32(bus(priv), CSR_EEPROM_REG, + iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, + ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -303,13 +303,13 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(bus(priv), CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); /* check for ECC errors: */ - otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); return -EINVAL; @@ -317,7 +317,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { /* continue in this case */ /* set the correctable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } @@ -424,14 +424,14 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { __le16 *e; - u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); + u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; u16 addr; u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwl_get_nvm_type(priv, hw_rev); + priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ @@ -469,11 +469,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - iwl_write32(bus(priv), CSR_EEPROM_GP, - iwl_read32(bus(priv), CSR_EEPROM_GP) & + iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ @@ -498,10 +498,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(bus(priv), CSR_EEPROM_REG, + iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, + ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -509,7 +509,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = iwl_read32(bus(priv), CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } @@ -838,7 +838,7 @@ void iwl_rf_config(struct iwl_priv *priv) /* write radio config values to register */ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); @@ -850,7 +850,7 @@ void iwl_rf_config(struct iwl_priv *priv) WARN_ON(1); /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e2b5e0ea5d9c..e4bf8ac5e64e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -301,6 +301,7 @@ void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); +int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h index 5bede9d7f955..0ad60b3c04db 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -63,8 +63,6 @@ #ifndef __iwl_fh_h__ #define __iwl_fh_h__ -#include - /****************************/ /* Flow Handler Definitions */ /****************************/ @@ -268,6 +266,8 @@ #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) +#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ + /** * Rx Shared Status Registers (RSSR) * @@ -422,6 +422,10 @@ #define RX_FREE_BUFFERS 64 #define RX_LOW_WATERMARK 8 +/* Size of one Rx buffer in host DRAM */ +#define IWL_RX_BUF_SIZE_4K (4 * 1024) +#define IWL_RX_BUF_SIZE_8K (8 * 1024) + /** * struct iwl_rb_status - reseve buffer status * host memory mapped FH registers @@ -504,16 +508,4 @@ struct iwl_tfd { /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ -/* Fixed (non-configurable) rx data from phy */ - -/** - * struct iwlagn_schedq_bc_tbl scheduler byte count table - * base physical address provided by SCD_DRAM_BASE_ADDR - * @tfd_offset 0-12 - tx command byte count - * 12-16 - station index - */ -struct iwlagn_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __packed; - #endif /* !__iwl_fh_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h index 968fc66e3506..9d91552d13c1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -35,16 +35,128 @@ #include "iwl-io.h" +#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) + + static inline struct ieee80211_conf *ieee80211_get_hw_conf( struct ieee80211_hw *hw) { return &hw->conf; } +/** + * iwl_queue_inc_wrap - increment queue index, wrap back to beginning + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_inc_wrap(int index, int n_bd) +{ + return ++index & (n_bd - 1); +} + +/** + * iwl_queue_dec_wrap - decrement queue index, wrap back to end + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_dec_wrap(int index, int n_bd) +{ + return --index & (n_bd - 1); +} + +/* + * we have 8 bits used like this: + * + * 7 6 5 4 3 2 1 0 + * | | | | | | | | + * | | | | | | +-+-------- AC queue (0-3) + * | | | | | | + * | +-+-+-+-+------------ HW queue ID + * | + * +---------------------- unused + */ +static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) +{ + BUG_ON(ac > 3); /* only have 2 bits */ + BUG_ON(hwq > 31); /* only use 5 bits */ + + txq->swq_id = (hwq << 2) | ac; +} + +static inline void iwl_wake_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (test_and_clear_bit(hwq, priv->queue_stopped)) + if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) + ieee80211_wake_queue(priv->hw, ac); +} + +static inline void iwl_stop_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (!test_and_set_bit(hwq, priv->queue_stopped)) + if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) + ieee80211_stop_queue(priv->hw, ac); +} + +static inline void iwl_wake_any_queue(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + u8 ac; + + for (ac = 0; ac < AC_NUM; ac++) { + IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", + ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) + ? "stopped" : "awake"); + iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); + } +} + +#ifdef ieee80211_stop_queue +#undef ieee80211_stop_queue +#endif + +#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue + +#ifdef ieee80211_wake_queue +#undef ieee80211_wake_queue +#endif + +#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue + +static inline void iwl_disable_interrupts(struct iwl_priv *priv) +{ + clear_bit(STATUS_INT_ENABLED, &priv->status); + + /* disable interrupts from uCode/NIC to host */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* acknowledge/clear/reset any interrupts still pending + * from uCode or flow handler (Rx/Tx DMA) */ + iwl_write32(priv, CSR_INT, 0xffffffff); + iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); + IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); +} + static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); - iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + +static inline void iwl_enable_interrupts(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); + set_bit(STATUS_INT_ENABLED, &priv->status); + iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); } /** diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c b/trunk/drivers/net/wireless/iwlwifi/iwl-io.c index 3ffa8e62b856..aa4a90674452 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.c @@ -25,50 +25,46 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ -#include -#include #include "iwl-io.h" -#include"iwl-csr.h" -#include "iwl-debug.h" #define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) | mask); + iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); } -static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask); + iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_set_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_set_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_clear_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_clear_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read32(bus, addr) & mask) == (bits & mask)) + if ((iwl_read32(priv, addr) & mask) == (bits & mask)) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -77,14 +73,14 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr, return -ETIMEDOUT; } -int iwl_grab_nic_access_silent(struct iwl_bus *bus) +int iwl_grab_nic_access_silent(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&bus->reg_lock); + lockdep_assert_held(&priv->reg_lock); /* this bit wakes up the NIC */ - __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * These bits say the device is running, and should keep running for @@ -105,70 +101,70 @@ int iwl_grab_nic_access_silent(struct iwl_bus *bus) * 5000 series and later (including 1000 series) have non-volatile SRAM, * and do not save/restore SRAM when power cycling. */ - ret = iwl_poll_bit(bus, CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } return 0; } -int iwl_grab_nic_access(struct iwl_bus *bus) +int iwl_grab_nic_access(struct iwl_priv *priv) { - int ret = iwl_grab_nic_access_silent(bus); + int ret = iwl_grab_nic_access_silent(priv); if (ret) { - u32 val = iwl_read32(bus, CSR_GP_CNTRL); - IWL_ERR(bus, + u32 val = iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); } return ret; } -void iwl_release_nic_access(struct iwl_bus *bus) +void iwl_release_nic_access(struct iwl_priv *priv) { - lockdep_assert_held(&bus->reg_lock); - __iwl_clear_bit(bus, CSR_GP_CNTRL, + lockdep_assert_held(&priv->reg_lock); + __iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg) +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) { u32 value; unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - value = iwl_read32(bus(bus), reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + value = iwl_read32(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); return value; } -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value) +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, reg, value); - iwl_release_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, reg, value); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read_direct32(bus, addr) & mask) == mask) + if ((iwl_read_direct32(priv, addr) & mask) == mask) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -177,122 +173,122 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, return -ETIMEDOUT; } -static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg) +static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) { - iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); rmb(); - return iwl_read32(bus, HBUS_TARG_PRPH_RDAT); + return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); } -static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { - iwl_write32(bus, HBUS_TARG_PRPH_WADDR, + iwl_write32(priv, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); wmb(); - iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val); + iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); } -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg) +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); return val; } -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - __iwl_write_prph(bus, addr, val); - iwl_release_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + __iwl_write_prph(priv, addr, val); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, - (__iwl_read_prph(bus, reg) & mask) | bits); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, + (__iwl_read_prph(priv, reg) & mask) | bits); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - __iwl_write_prph(bus, reg, (val & ~mask)); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + __iwl_write_prph(priv, reg, (val & ~mask)); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void *buf, int words) { unsigned long flags; int offs; u32 *vals = buf; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); - iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); rmb(); for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) { u32 value; - _iwl_read_targ_mem_words(bus, addr, &value, 1); + _iwl_read_targ_mem_words(priv, addr, &value, 1); return value; } -void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val) +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); wmb(); - iwl_write32(bus, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(bus); + iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h index ced2cbeb6eae..19a093101122 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h @@ -29,62 +29,65 @@ #ifndef __iwl_io_h__ #define __iwl_io_h__ +#include + +#include "iwl-dev.h" +#include "iwl-debug.h" #include "iwl-devtrace.h" -#include "iwl-shared.h" #include "iwl-bus.h" -static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) +static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { - trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); - bus_write8(bus, ofs, val); + trace_iwlwifi_dev_iowrite8(priv, ofs, val); + bus_write8(priv->bus, ofs, val); } -static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) +static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { - trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); - bus_write32(bus, ofs, val); + trace_iwlwifi_dev_iowrite32(priv, ofs, val); + bus_write32(priv->bus, ofs, val); } -static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) +static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) { - u32 val = bus_read32(bus, ofs); - trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); + u32 val = bus_read32(priv->bus, ofs); + trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout); -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout); -int iwl_grab_nic_access_silent(struct iwl_bus *bus); -int iwl_grab_nic_access(struct iwl_bus *bus); -void iwl_release_nic_access(struct iwl_bus *bus); +int iwl_grab_nic_access_silent(struct iwl_priv *priv); +int iwl_grab_nic_access(struct iwl_priv *priv); +void iwl_release_nic_access(struct iwl_priv *priv); -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg); -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value); +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg); -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val); -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void *buf, int words); -#define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \ +#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ do { \ BUILD_BUG_ON((bufsize) % sizeof(u32)); \ - _iwl_read_targ_mem_words(bus, addr, buf, \ + _iwl_read_targ_mem_words(priv, addr, buf, \ (bufsize) / sizeof(u32));\ } while (0) -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr); -void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val); +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); #endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c index 7dffed186f0a..1a5252d8ca73 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c @@ -40,7 +40,6 @@ #include "iwl-agn.h" #include "iwl-io.h" #include "iwl-trans.h" -#include "iwl-shared.h" /* Throughput OFF time(ms) ON time (ms) * >300 25 25 @@ -71,7 +70,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* Set led register off */ void iwlagn_led_enable(struct iwl_priv *priv) { - iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); } /* @@ -108,11 +107,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) }; u32 reg; - reg = iwl_read32(bus(priv), CSR_LED_REG); + reg = iwl_read32(priv, CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } /* Set led pattern command */ @@ -126,7 +125,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, }; int ret; - if (!test_bit(STATUS_READY, &priv->shrd->status)) + if (!test_bit(STATUS_READY, &priv->status)) return -EBUSY; if (priv->blink_on == on && priv->blink_off == off) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c index 78a3f8dfe680..69d4ec467dca 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -64,11 +64,9 @@ #include #include "iwl-bus.h" +#include "iwl-agn.h" +#include "iwl-core.h" #include "iwl-io.h" -#include "iwl-shared.h" -#include "iwl-trans.h" -#include "iwl-csr.h" -#include "iwl-pci.h" /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -93,7 +91,6 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) { int pos; u16 pci_lnk_ctl; - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); pos = pci_pcie_cap(pci_dev); @@ -123,21 +120,21 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(bus, CSR_GIO_REG, + iwl_set_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(bus, CSR_GIO_REG, + iwl_clear_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } } -static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd) +static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { - bus->shrd = shrd; - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd); + bus->drv_data = drv_data; + pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -165,7 +162,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) return val; } -static const struct iwl_bus_ops bus_ops_pci = { +static struct iwl_bus_ops pci_ops = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .set_drv_data = iwl_pci_set_drv_data, @@ -259,7 +256,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, /* 6x30 Series */ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, @@ -332,7 +328,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, - {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)}, /* 2x30 Series */ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, @@ -462,9 +457,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bus->dev = &pdev->dev; bus->irq = pdev->irq; - bus->ops = &bus_ops_pci; + bus->ops = &pci_ops; - err = iwl_probe(bus, &trans_ops_pcie, cfg); + err = iwl_probe(bus, cfg); if (err) goto out_disable_msi; return 0; @@ -483,13 +478,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } -static void __devexit iwl_pci_remove(struct pci_dev *pdev) +static void iwl_pci_down(struct iwl_bus *bus) { - struct iwl_shared *shrd = pci_get_drvdata(pdev); - struct iwl_bus *bus = shrd->bus; - struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); - - iwl_remove(shrd->priv); + struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific; pci_disable_msi(pci_bus->pci_dev); pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); @@ -500,25 +491,35 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) kfree(bus); } -#ifdef CONFIG_PM_SLEEP +static void __devexit iwl_pci_remove(struct pci_dev *pdev) +{ + struct iwl_priv *priv = pci_get_drvdata(pdev); + void *bus_specific = priv->bus->bus_specific; + + iwl_remove(priv); + + iwl_pci_down(bus_specific); +} + +#ifdef CONFIG_PM static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_shared *shrd = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_trans_suspend(shrd->trans); + return iwl_suspend(priv); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_shared *shrd = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if @@ -531,7 +532,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_trans_resume(shrd->trans); + return iwl_resume(priv); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h deleted file mode 100644 index c0aea9e092cb..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - *****************************************************************************/ -#ifndef __iwl_pci_h__ -#define __iwl_pci_h__ - - -/* This file includes the declaration that are internal to the PCI - * implementation of the bus layer - */ - -/* configuration for the _agn devices */ -extern struct iwl_cfg iwl5300_agn_cfg; -extern struct iwl_cfg iwl5100_agn_cfg; -extern struct iwl_cfg iwl5350_agn_cfg; -extern struct iwl_cfg iwl5100_bgn_cfg; -extern struct iwl_cfg iwl5100_abg_cfg; -extern struct iwl_cfg iwl5150_agn_cfg; -extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6005_2agn_cfg; -extern struct iwl_cfg iwl6005_2abg_cfg; -extern struct iwl_cfg iwl6005_2bg_cfg; -extern struct iwl_cfg iwl6005_2agn_sff_cfg; -extern struct iwl_cfg iwl1030_bgn_cfg; -extern struct iwl_cfg iwl1030_bg_cfg; -extern struct iwl_cfg iwl6030_2agn_cfg; -extern struct iwl_cfg iwl6030_2abg_cfg; -extern struct iwl_cfg iwl6030_2bgn_cfg; -extern struct iwl_cfg iwl6030_2bg_cfg; -extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_2abg_cfg; -extern struct iwl_cfg iwl6000i_2bg_cfg; -extern struct iwl_cfg iwl6000_3agn_cfg; -extern struct iwl_cfg iwl6050_2agn_cfg; -extern struct iwl_cfg iwl6050_2abg_cfg; -extern struct iwl_cfg iwl6150_bgn_cfg; -extern struct iwl_cfg iwl6150_bg_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; -extern struct iwl_cfg iwl1000_bg_cfg; -extern struct iwl_cfg iwl100_bgn_cfg; -extern struct iwl_cfg iwl100_bg_cfg; -extern struct iwl_cfg iwl130_bgn_cfg; -extern struct iwl_cfg iwl130_bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_cfg; -extern struct iwl_cfg iwl2000_2bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_d_cfg; -extern struct iwl_cfg iwl2030_2bgn_cfg; -extern struct iwl_cfg iwl2030_2bg_cfg; -extern struct iwl_cfg iwl6035_2agn_cfg; -extern struct iwl_cfg iwl6035_2abg_cfg; -extern struct iwl_cfg iwl6035_2bg_cfg; -extern struct iwl_cfg iwl105_bg_cfg; -extern struct iwl_cfg iwl105_bgn_cfg; -extern struct iwl_cfg iwl135_bg_cfg; -extern struct iwl_cfg iwl135_bgn_cfg; - -#endif /* __iwl_pci_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c index 62cd781192b0..cd64df05f9ed 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c @@ -43,7 +43,6 @@ #include "iwl-debug.h" #include "iwl-power.h" #include "iwl-trans.h" -#include "iwl-shared.h" /* * Setting power level allows the card to go to sleep when not busy. @@ -215,7 +214,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (priv->cfg->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -301,7 +300,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.bus_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (priv->cfg->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -336,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } @@ -348,7 +347,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->shrd->wowlan) + if (priv->wowlan) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); else if (!priv->cfg->base_params->no_idle_support && priv->hw->conf.flags & IEEE80211_CONF_IDLE) @@ -383,7 +382,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, int ret; bool update_chains; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || @@ -392,23 +391,23 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) return 0; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete use sleep_power_next, need to be updated */ memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) { + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); return 0; } if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->shrd->status); + set_bit(STATUS_POWER_PMI, &priv->status); ret = iwl_set_power(priv, cmd); if (!ret) { if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->shrd->status); + clear_bit(STATUS_POWER_PMI, &priv->status); if (update_chains) iwl_update_chain_flags(priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h index bebdd828f324..2f267b8aabbb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -217,8 +217,8 @@ ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) #define SCD_QUEUECHAIN_SEL_ALL(priv) \ - (((1<shrd->cmd_queue))) + (((1<<(priv)->hw_params.max_txq_num) - 1) &\ + (~(1<<(priv)->cmd_queue))) #define SCD_BASE (PRPH_BASE + 0xa02c00) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index c7e6a746c3ea..8e314003b63a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -40,89 +40,7 @@ #include "iwl-helpers.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-shared.h" -const char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IWL_CMD(REPLY_ALIVE); - IWL_CMD(REPLY_ERROR); - IWL_CMD(REPLY_RXON); - IWL_CMD(REPLY_RXON_ASSOC); - IWL_CMD(REPLY_QOS_PARAM); - IWL_CMD(REPLY_RXON_TIMING); - IWL_CMD(REPLY_ADD_STA); - IWL_CMD(REPLY_REMOVE_STA); - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_TXFIFO_FLUSH); - IWL_CMD(REPLY_WEPKEY); - IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(COEX_PRIORITY_TABLE_CMD); - IWL_CMD(COEX_MEDIUM_NOTIFICATION); - IWL_CMD(COEX_EVENT_CMD); - IWL_CMD(REPLY_QUIET_CMD); - IWL_CMD(REPLY_CHANNEL_SWITCH); - IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); - IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); - IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); - IWL_CMD(POWER_TABLE_CMD); - IWL_CMD(PM_SLEEP_NOTIFICATION); - IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); - IWL_CMD(REPLY_SCAN_CMD); - IWL_CMD(REPLY_SCAN_ABORT_CMD); - IWL_CMD(SCAN_START_NOTIFICATION); - IWL_CMD(SCAN_RESULTS_NOTIFICATION); - IWL_CMD(SCAN_COMPLETE_NOTIFICATION); - IWL_CMD(BEACON_NOTIFICATION); - IWL_CMD(REPLY_TX_BEACON); - IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); - IWL_CMD(QUIET_NOTIFICATION); - IWL_CMD(REPLY_TX_PWR_TABLE_CMD); - IWL_CMD(MEASURE_ABORT_NOTIFICATION); - IWL_CMD(REPLY_BT_CONFIG); - IWL_CMD(REPLY_STATISTICS_CMD); - IWL_CMD(STATISTICS_NOTIFICATION); - IWL_CMD(REPLY_CARD_STATE_CMD); - IWL_CMD(CARD_STATE_NOTIFICATION); - IWL_CMD(MISSED_BEACONS_NOTIFICATION); - IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); - IWL_CMD(SENSITIVITY_CMD); - IWL_CMD(REPLY_PHY_CALIBRATION_CMD); - IWL_CMD(REPLY_RX_PHY_CMD); - IWL_CMD(REPLY_RX_MPDU_CMD); - IWL_CMD(REPLY_RX); - IWL_CMD(REPLY_COMPRESSED_BA); - IWL_CMD(CALIBRATION_CFG_CMD); - IWL_CMD(CALIBRATION_RES_NOTIFICATION); - IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); - IWL_CMD(REPLY_TX_POWER_DBM_CMD); - IWL_CMD(TEMPERATURE_NOTIFICATION); - IWL_CMD(TX_ANT_CONFIGURATION_CMD); - IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); - IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); - IWL_CMD(REPLY_BT_COEX_PROT_ENV); - IWL_CMD(REPLY_WIPAN_PARAMS); - IWL_CMD(REPLY_WIPAN_RXON); - IWL_CMD(REPLY_WIPAN_RXON_TIMING); - IWL_CMD(REPLY_WIPAN_RXON_ASSOC); - IWL_CMD(REPLY_WIPAN_QOS_PARAM); - IWL_CMD(REPLY_WIPAN_WEPKEY); - IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); - IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); - IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); - IWL_CMD(REPLY_WOWLAN_PATTERNS); - IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER); - IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS); - IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); - IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); - IWL_CMD(REPLY_WOWLAN_GET_STATUS); - default: - return "UNKNOWN"; - - } -} /****************************************************************************** * @@ -155,7 +73,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) return; if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { @@ -203,8 +121,7 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 __maybe_unused len = - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", len, get_cmd_string(pkt->hdr.cmd)); @@ -231,8 +148,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - queue_work(priv->shrd->workqueue, &priv->beacon_update); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + queue_work(priv->workqueue, &priv->beacon_update); } /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ @@ -341,7 +258,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, { unsigned int msecs; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); @@ -557,7 +474,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, priv->rx_statistics_jiffies = stamp; - set_bit(STATUS_STATISTICS, &priv->shrd->status); + set_bit(STATUS_STATISTICS, &priv->status); /* Reschedule the statistics timer to occur in * reg_recalib_period seconds to ensure we get a @@ -566,10 +483,10 @@ static void iwl_rx_statistics(struct iwl_priv *priv, mod_timer(&priv->statistics_periodic, jiffies + msecs_to_jiffies(reg_recalib_period * 1000)); - if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) && + if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwl_rx_calc_noise(priv); - queue_work(priv->shrd->workqueue, &priv->run_time_calib_work); + queue_work(priv->workqueue, &priv->run_time_calib_work); } if (priv->cfg->lib->temperature && change) priv->cfg->lib->temperature(priv); @@ -601,7 +518,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); - unsigned long status = priv->shrd->status; + unsigned long status = priv->status; IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", @@ -612,16 +529,16 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } if (flags & CT_CARD_DISABLED) @@ -631,20 +548,20 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, iwl_tt_exit_ct_kill(priv); if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); if (!(flags & RXON_CARD_DISABLED)) iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status))) + test_bit(STATUS_RF_KILL_HW, &priv->status))) wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); else - wake_up_interruptible(&priv->shrd->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, @@ -663,7 +580,7 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) + if (!test_bit(STATUS_SCANNING, &priv->status)) iwl_init_sensitivity(priv); } } @@ -780,7 +697,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, ctx->active.bssid_addr)) continue; ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), ctx->ctxid); + iwl_wake_any_queue(priv, ctx); } } @@ -1101,7 +1018,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) * handle those that need handling via function in * rx_handlers table. See iwl_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->rx_handlers_stats[pkt->hdr.cmd]++; + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index fc5af3475392..28e59319f581 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -68,14 +68,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform * hardware scan currently */ - if (!test_bit(STATUS_READY, &priv->shrd->status) || - !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || - !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || - test_bit(STATUS_FW_ERROR, &priv->shrd->status) || - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_READY, &priv->status) || + !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || + !test_bit(STATUS_SCAN_HW, &priv->status) || + test_bit(STATUS_FW_ERROR, &priv->status) || + test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EIO; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -91,7 +91,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) ret = -EIO; } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -116,17 +116,17 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) void iwl_force_scan_end(struct iwl_priv *priv) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); return; } IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); - clear_bit(STATUS_SCANNING, &priv->shrd->status); - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); - clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCAN_ABORTING, &priv->status); iwl_complete_scan(priv, true); } @@ -134,14 +134,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); return; } - if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); return; } @@ -160,7 +160,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) int iwl_scan_cancel(struct iwl_priv *priv) { IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); - queue_work(priv->shrd->workqueue, &priv->abort_scan); + queue_work(priv->workqueue, &priv->abort_scan); return 0; } @@ -173,19 +173,19 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long timeout = jiffies + msecs_to_jiffies(ms); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); iwl_do_scan_abort(priv); while (time_before_eq(jiffies, timeout)) { - if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (!test_bit(STATUS_SCAN_HW, &priv->status)) break; msleep(20); } - return test_bit(STATUS_SCAN_HW, &priv->shrd->status); + return test_bit(STATUS_SCAN_HW, &priv->status); } /* Service response to REPLY_SCAN_CMD (0x80) */ @@ -257,13 +257,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->tsf_high, scan_notif->status); /* The HW is no longer scanning */ - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->status); IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - priv->scan_start)); - queue_work(priv->shrd->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->scan_completed); if (priv->iw_mode != NL80211_IFTYPE_ADHOC && iwl_advanced_bt_coexist(priv) && @@ -283,8 +283,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = scan_notif->bt_status; - queue_work(priv->shrd->workqueue, - &priv->bt_traffic_change_work); + queue_work(priv->workqueue, &priv->bt_traffic_change_work); } } @@ -344,7 +343,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, void iwl_init_scan_params(struct iwl_priv *priv) { - u8 ant_idx = fls(hw_params(priv).valid_tx_ant) - 1; + u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) @@ -358,22 +357,22 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); cancel_delayed_work(&priv->scan_check); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Request scan called when driver not ready.\n"); return -EIO; } - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_SCAN(priv, "Multiple concurrent scan requests in parallel.\n"); return -EBUSY; } - if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); return -EBUSY; } @@ -383,19 +382,19 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, scan_type == IWL_SCAN_ROC ? "remain-on-channel " : "internal short "); - set_bit(STATUS_SCANNING, &priv->shrd->status); + set_bit(STATUS_SCANNING, &priv->status); priv->scan_type = scan_type; priv->scan_start = jiffies; priv->scan_band = band; ret = iwlagn_request_scan(priv, vif); if (ret) { - clear_bit(STATUS_SCANNING, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); priv->scan_type = IWL_SCAN_NORMAL; return ret; } - queue_delayed_work(priv->shrd->workqueue, &priv->scan_check, + queue_delayed_work(priv->workqueue, &priv->scan_check, IWL_SCAN_CHECK_WATCHDOG); return 0; @@ -413,9 +412,9 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, if (req->n_channels == 0) return -EINVAL; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && + if (test_bit(STATUS_SCANNING, &priv->status) && priv->scan_type != IWL_SCAN_NORMAL) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); ret = -EAGAIN; @@ -440,7 +439,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -451,7 +450,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, */ void iwl_internal_short_hw_scan(struct iwl_priv *priv) { - queue_work(priv->shrd->workqueue, &priv->start_internal_scan); + queue_work(priv->workqueue, &priv->start_internal_scan); } static void iwl_bg_start_internal_scan(struct work_struct *work) @@ -461,14 +460,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) IWL_DEBUG_SCAN(priv, "Start internal scan\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->scan_type == IWL_SCAN_RADIO_RESET) { IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); goto unlock; } - if (test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); goto unlock; } @@ -476,7 +475,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); unlock: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_check(struct work_struct *data) @@ -489,9 +488,9 @@ static void iwl_bg_scan_check(struct work_struct *data) /* Since we are here firmware does not finish scan and * most likely is in bad shape, so we don't bother to * send abort command, just force scan complete to mac80211 */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -549,9 +548,9 @@ static void iwl_bg_abort_scan(struct work_struct *work) /* We keep scan_check work queued in case when firmware will not * report back scan completed notification */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 200); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_completed(struct work_struct *work) @@ -564,13 +563,13 @@ static void iwl_bg_scan_completed(struct work_struct *work) cancel_delayed_work(&priv->scan_check); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); if (aborted) IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); - if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); goto out_settings; } @@ -606,13 +605,13 @@ static void iwl_bg_scan_completed(struct work_struct *work) out_settings: /* Can we still talk to firmware ? */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) goto out; iwlagn_post_scan(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwl_setup_scan_deferred_work(struct iwl_priv *priv) @@ -630,8 +629,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->scan_completed); if (cancel_delayed_work_sync(&priv->scan_check)) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h deleted file mode 100644 index d987bee5e6ce..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h +++ /dev/null @@ -1,482 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS 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. - * - *****************************************************************************/ -#ifndef __iwl_shared_h__ -#define __iwl_shared_h__ - -#include -#include -#include -#include -#include /* for page_address */ -#include - -#include "iwl-commands.h" - -/*This files includes all the types / functions that are exported by the - * upper layer to the bus and transport layer */ - -struct iwl_cfg; -struct iwl_bus; -struct iwl_priv; -struct iwl_sensitivity_ranges; -struct iwl_trans_ops; - -#define DRV_NAME "iwlagn" -#define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" -#define DRV_AUTHOR "" - -extern struct iwl_mod_params iwlagn_mod_params; - -/** - * struct iwl_mod_params - * @sw_crypto: using hardware encryption, default = 0 - * @num_of_queues: number of tx queue, HW dependent - * @disable_11n: 11n capabilities enabled, default = 0 - * @amsdu_size_8K: enable 8K amsdu size, default = 1 - * @antenna: both antennas (use diversity), default = 0 - * @restart_fw: restart firmware, default = 1 - * @plcp_check: enable plcp health check, default = true - * @ack_check: disable ack health check, default = false - * @wd_disable: enable stuck queue check, default = false - * @bt_coex_active: enable bt coex, default = true - * @led_mode: system default, default = 0 - * @no_sleep_autoadjust: disable autoadjust, default = true - * @power_save: disable power save, default = false - * @power_level: power level, default = 1 - * @debug_level: levels are IWL_DL_* - * @ant_coupling: antenna coupling in dB, default = 0 - * @bt_ch_announce: BT channel inhibition, default = enable - * @wanted_ucode_alternative: ucode alternative to use, default = 1 - * @auto_agg: enable agg. without check, default = true - */ -struct iwl_mod_params { - int sw_crypto; - int num_of_queues; - int disable_11n; - int amsdu_size_8K; - int antenna; - int restart_fw; - bool plcp_check; - bool ack_check; - bool wd_disable; - bool bt_coex_active; - int led_mode; - bool no_sleep_autoadjust; - bool power_save; - int power_level; - u32 debug_level; - int ant_coupling; - bool bt_ch_announce; - int wanted_ucode_alternative; - bool auto_agg; -}; - -/** - * struct iwl_hw_params - * @max_txq_num: Max # Tx queues supported - * @num_ampdu_queues: num of ampdu queues - * @tx/rx_chains_num: Number of TX/RX chains - * @valid_tx/rx_ant: usable antennas - * @max_stations: - * @ht40_channel: is 40MHz width possible in band 2.4 - * @beacon_time_tsf_bits: number of valid tsf bits for beacon time - * @sku: - * @rx_page_order: Rx buffer page order - * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR - * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) - * @sw_crypto: 0 for hw, 1 for sw - * @max_xxx_size: for ucode uses - * @ct_kill_threshold: temperature threshold - * @wd_timeout: TX queues watchdog timeout - * @calib_init_cfg: setup initial calibrations for the hw - * @calib_rt_cfg: setup runtime calibrations for the hw - * @struct iwl_sensitivity_ranges: range of sensitivity values - */ -struct iwl_hw_params { - u8 max_txq_num; - u8 num_ampdu_queues; - u8 tx_chains_num; - u8 rx_chains_num; - u8 valid_tx_ant; - u8 valid_rx_ant; - u8 max_stations; - u8 ht40_channel; - bool shadow_reg_enable; - u16 beacon_time_tsf_bits; - u16 sku; - u32 rx_page_order; - u32 max_inst_size; - u32 max_data_size; - u32 ct_kill_threshold; /* value in hw-dependent units */ - u32 ct_kill_exit_threshold; /* value in hw-dependent units */ - /* for 1000, 6000 series and up */ - unsigned int wd_timeout; - - u32 calib_init_cfg; - u32 calib_rt_cfg; - const struct iwl_sensitivity_ranges *sens; -}; - -/** - * struct iwl_ht_agg - aggregation status while waiting for block-ack - * @txq_id: Tx queue used for Tx attempt - * @wait_for_ba: Expect block-ack before next Tx reply - * @rate_n_flags: Rate at which Tx was attempted - * - * If REPLY_TX indicates that aggregation was attempted, driver must wait - * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info - * until block ack arrives. - */ -struct iwl_ht_agg { - u16 txq_id; - u16 wait_for_ba; - u32 rate_n_flags; -#define IWL_AGG_OFF 0 -#define IWL_AGG_ON 1 -#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 -#define IWL_EMPTYING_HW_QUEUE_DELBA 3 - u8 state; -}; - -struct iwl_tid_data { - u16 seq_number; /* agn only */ - u16 tfds_in_queue; - struct iwl_ht_agg agg; -}; - -/** - * struct iwl_shared - shared fields for all the layers of the driver - * - * @dbg_level_dev: dbg level set per device. Prevails on - * iwlagn_mod_params.debug_level if set (!= 0) - * @ucode_owner: IWL_OWNERSHIP_* - * @cmd_queue: command queue number - * @status: STATUS_* - * @valid_contexts: microcode/device supports multiple contexts - * @bus: pointer to the bus layer data - * @priv: pointer to the upper layer data - * @hw_params: see struct iwl_hw_params - * @workqueue: the workqueue used by all the layers of the driver - * @lock: protect general shared data - * @sta_lock: protects the station table. - * If lock and sta_lock are needed, lock must be acquired first. - * @mutex: - */ -struct iwl_shared { -#ifdef CONFIG_IWLWIFI_DEBUG - u32 dbg_level_dev; -#endif /* CONFIG_IWLWIFI_DEBUG */ - -#define IWL_OWNERSHIP_DRIVER 0 -#define IWL_OWNERSHIP_TM 1 - u8 ucode_owner; - u8 cmd_queue; - unsigned long status; - bool wowlan; - u8 valid_contexts; - - struct iwl_bus *bus; - struct iwl_priv *priv; - struct iwl_trans *trans; - struct iwl_hw_params hw_params; - - struct workqueue_struct *workqueue; - spinlock_t lock; - spinlock_t sta_lock; - struct mutex mutex; - - /*these 2 shouldn't really be here, but they are needed for - * iwl_queue_stop, which is called from the upper layer too - */ - u8 mac80211_registered; - struct ieee80211_hw *hw; - - struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; - - wait_queue_head_t wait_command_queue; -}; - -/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ -#define priv(_m) ((_m)->shrd->priv) -#define bus(_m) ((_m)->shrd->bus) -#define trans(_m) ((_m)->shrd->trans) -#define hw_params(_m) ((_m)->shrd->hw_params) - -#ifdef CONFIG_IWLWIFI_DEBUG -/* - * iwl_get_debug_level: Return active debug level for device - * - * Using sysfs it is possible to set per device debug level. This debug - * level will be used if set, otherwise the global debug level which can be - * set via module parameter is used. - */ -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) -{ - if (shrd->dbg_level_dev) - return shrd->dbg_level_dev; - else - return iwlagn_mod_params.debug_level; -} -#else -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) -{ - return iwlagn_mod_params.debug_level; -} -#endif - -static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page) -{ - free_pages(page, shrd->hw_params.rx_page_order); -} - -/** - * iwl_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl_queue_dec_wrap - decrement queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} - -struct iwl_rx_mem_buffer { - dma_addr_t page_dma; - struct page *page; - struct list_head list; -}; - -#define rxb_addr(r) page_address(r->page) - -/* - * mac80211 queues, ACs, hardware queues, FIFOs. - * - * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues - * - * Mac80211 uses the following numbers, which we get as from it - * by way of skb_get_queue_mapping(skb): - * - * VO 0 - * VI 1 - * BE 2 - * BK 3 - * - * - * Regular (not A-MPDU) frames are put into hardware queues corresponding - * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their - * own queue per aggregation session (RA/TID combination), such queues are - * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In - * order to map frames to the right queue, we also need an AC->hw queue - * mapping. This is implemented here. - * - * Due to the way hw queues are set up (by the hw specific modules like - * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity - * mapping. - */ - -static const u8 tid_to_ac[] = { - IEEE80211_AC_BE, - IEEE80211_AC_BK, - IEEE80211_AC_BK, - IEEE80211_AC_BE, - IEEE80211_AC_VI, - IEEE80211_AC_VI, - IEEE80211_AC_VO, - IEEE80211_AC_VO -}; - -static inline int get_ac_from_tid(u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return tid_to_ac[tid]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -enum iwl_rxon_context_id { - IWL_RXON_CTX_BSS, - IWL_RXON_CTX_PAN, - - NUM_IWL_RXON_CTX -}; - -#ifdef CONFIG_PM -int iwl_suspend(struct iwl_priv *priv); -int iwl_resume(struct iwl_priv *priv); -#endif /* !CONFIG_PM */ - -int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, - struct iwl_cfg *cfg); -void __devexit iwl_remove(struct iwl_priv * priv); - -void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -int iwlagn_hw_valid_rtc_data_addr(u32 addr); -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid); -void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid); -void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); -void iwl_nic_config(struct iwl_priv *priv); -void iwl_apm_stop(struct iwl_priv *priv); -int iwl_apm_init(struct iwl_priv *priv); -void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); -const char *get_cmd_string(u8 cmd); -bool iwl_check_for_ct_kill(struct iwl_priv *priv); - -#ifdef CONFIG_IWLWIFI_DEBUGFS -void iwl_reset_traffic_log(struct iwl_priv *priv); -#endif /* CONFIG_IWLWIFI_DEBUGFS */ - -#ifdef CONFIG_IWLWIFI_DEBUG -void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid); -#else -static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid) -{ -} -#endif - -#define IWL_CMD(x) case x: return #x -#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) - -#define IWL_TRAFFIC_ENTRIES (256) -#define IWL_TRAFFIC_ENTRY_SIZE (64) - -/***************************************************** -* DRIVER STATUS FUNCTIONS -******************************************************/ -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_CT_KILL 4 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_DEVICE_ENABLED 18 -#define STATUS_CHANNEL_SWITCH_PENDING 19 - -static inline int iwl_is_ready(struct iwl_shared *shrd) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &shrd->status) && - test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && - !test_bit(STATUS_EXIT_PENDING, &shrd->status); -} - -static inline int iwl_is_alive(struct iwl_shared *shrd) -{ - return test_bit(STATUS_ALIVE, &shrd->status); -} - -static inline int iwl_is_init(struct iwl_shared *shrd) -{ - return test_bit(STATUS_INIT, &shrd->status); -} - -static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) -{ - return test_bit(STATUS_RF_KILL_HW, &shrd->status); -} - -static inline int iwl_is_rfkill(struct iwl_shared *shrd) -{ - return iwl_is_rfkill_hw(shrd); -} - -static inline int iwl_is_ctkill(struct iwl_shared *shrd) -{ - return test_bit(STATUS_CT_KILL, &shrd->status); -} - -static inline int iwl_is_ready_rf(struct iwl_shared *shrd) -{ - if (iwl_is_rfkill(shrd)) - return 0; - - return iwl_is_ready(shrd); -} - -#endif /* #__iwl_shared_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index e24135e7d37d..1ef3b7106ad5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -38,7 +38,7 @@ #include "iwl-trans.h" #include "iwl-agn.h" -/* priv->shrd->sta_lock must be held */ +/* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { @@ -75,7 +75,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: @@ -118,19 +118,19 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, priv->stations[sta_id].sta.mode == STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } -static void iwl_add_sta_callback(struct iwl_shared *shrd, +static void iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt) { struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)cmd->cmd.payload; - iwl_process_add_sta_resp(shrd->priv, addsta, pkt, false); + iwl_process_add_sta_resp(priv, addsta, pkt, false); } @@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -177,7 +177,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, pkt = (struct iwl_rx_packet *)cmd.reply_page; ret = iwl_process_add_sta_resp(priv, sta, pkt, true); } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -251,8 +251,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, else if (is_broadcast_ether_addr(addr)) sta_id = ctx->bcast_sta_id; else - for (i = IWL_STA_ID; - i < hw_params(priv).max_stations; i++) { + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { sta_id = i; @@ -337,12 +336,12 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_addsta_cmd sta_cmd; *sta_id_r = 0; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EINVAL; } @@ -354,7 +353,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EEXIST; } @@ -362,23 +361,23 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", sta_id, addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EEXIST; } priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } *sta_id_r = sta_id; return ret; @@ -387,7 +386,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station * - * priv->shrd->sta_lock must be held + * priv->sta_lock must be held */ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) { @@ -425,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -441,11 +440,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: if (!temporary) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; @@ -455,7 +452,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, break; } } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -468,7 +465,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, { unsigned long flags; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Unable to remove station %pM, device not ready.\n", addr); @@ -486,7 +483,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(sta_id == IWL_INVALID_STATION)) return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", @@ -512,11 +509,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(priv->num_stations < 0)) priv->num_stations = 0; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_remove_station(priv, addr, sta_id, false); out_err: - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; } @@ -537,8 +534,8 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (ctx && ctx->ctxid != priv->stations[i].ctxid) continue; @@ -548,7 +545,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, cleared = true; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); if (!cleared) IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); @@ -572,14 +569,14 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int ret; bool send_lq; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); return; } IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (ctx->ctxid != priv->stations[i].ctxid) continue; if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && @@ -592,7 +589,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } } - for (i = 0; i < hw_params(priv).max_stations; i++) { + for (i = 0; i < priv->hw_params.max_stations; i++) { if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { memcpy(&sta_cmd, &priv->stations[i].sta, sizeof(struct iwl_addsta_cmd)); @@ -602,18 +599,15 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) sizeof(struct iwl_link_quality_cmd)); send_lq = true; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[i].sta.sta.addr); priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } /* * Rate scaling has already been initialized, send @@ -621,12 +615,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) */ if (send_lq) iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); if (!found) IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); else @@ -642,9 +636,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) struct iwl_link_quality_cmd lq; bool active; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return; } @@ -654,7 +648,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); if (active) { ret = iwl_send_remove_station( @@ -664,9 +658,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_ERR(priv, "failed to remove STA %pM (%d)\n", priv->stations[sta_id].sta.sta.addr, ret); } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) @@ -691,8 +685,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) unsigned long flags; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (!(priv->stations[i].used & IWL_STA_BCAST)) continue; @@ -703,7 +697,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } #ifdef CONFIG_IWLWIFI_DEBUG @@ -787,19 +781,19 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EINVAL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); iwl_dump_lq_cmd(priv, lq); if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); else ret = -EINVAL; @@ -809,9 +803,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (init) { IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", lq->sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } return ret; } @@ -826,13 +820,13 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr); ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h index 9641eb6b1d0a..9a6768d66851 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -76,7 +76,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) unsigned long flags; struct iwl_rxon_context *ctx; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memset(priv->stations, 0, sizeof(priv->stations)); priv->num_stations = 0; @@ -94,7 +94,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) ctx->key_mapping_keys = 0; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } static inline int iwl_sta_id(struct ieee80211_sta *sta) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 3335d31daf89..b11f60de4f1e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include #include @@ -73,6 +72,7 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-debug.h" +#include "iwl-fh.h" #include "iwl-io.h" #include "iwl-agn.h" #include "iwl-testmode.h" @@ -239,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -277,7 +277,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_REG_READ32: - val32 = iwl_read32(bus(priv), ofs); + val32 = iwl_read32(priv, ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -299,7 +299,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(bus(priv), ofs, val32); + iwl_write32(priv, ofs, val32); } break; case IWL_TM_CMD_APP2DEV_REG_WRITE8: @@ -309,7 +309,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); IWL_INFO(priv, "8bit value to write 0x%x\n", val8); - iwl_write8(bus(priv), ofs, val8); + iwl_write8(priv, ofs, val8); } break; default: @@ -405,7 +405,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: @@ -613,7 +613,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) - priv->shrd->ucode_owner = owner; + priv->ucode_owner = owner; else { IWL_DEBUG_INFO(priv, "Invalid owner\n"); return -EINVAL; @@ -661,7 +661,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) return -ENOMSG; } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_UCODE: @@ -702,7 +702,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } @@ -738,7 +738,7 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (cmd) { case IWL_TM_CMD_APP2DEV_READ_TRACE: IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); @@ -749,6 +749,6 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 8047e955a27b..b79330d84185 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -29,426 +29,54 @@ #ifndef __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__ -#include -#include -#include -#include - -#include "iwl-fh.h" -#include "iwl-csr.h" -#include "iwl-shared.h" -#include "iwl-trans.h" -#include "iwl-debug.h" -#include "iwl-io.h" - -struct iwl_tx_queue; -struct iwl_queue; -struct iwl_host_cmd; - /*This file includes the declaration that are internal to the * trans_pcie layer */ -/** - * struct isr_statistics - interrupt statistics - * - */ -struct isr_statistics { - u32 hw; - u32 sw; - u32 err_code; - u32 sch; - u32 alive; - u32 rfkill; - u32 ctkill; - u32 wakeup; - u32 rx; - u32 tx; - u32 unhandled; -}; - -/** - * struct iwl_rx_queue - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) - * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) - * @pool: - * @queue: - * @read: Shared index to newest available Rx buffer - * @write: Shared index to oldest written Rx packet - * @free_count: Number of pre-allocated buffers in rx_free - * @write_actual: - * @rx_free: list of free SKBs for use - * @rx_used: List of Rx buffers with no SKB - * @need_update: flag to indicate we need to update read/write index - * @rb_stts: driver's pointer to receive buffer status - * @rb_stts_dma: bus address of receive buffer status - * @lock: - * - * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers - */ -struct iwl_rx_queue { - __le32 *bd; - dma_addr_t bd_dma; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 read; - u32 write; - u32 free_count; - u32 write_actual; - struct list_head rx_free; - struct list_head rx_used; - int need_update; - struct iwl_rb_status *rb_stts; - dma_addr_t rb_stts_dma; - spinlock_t lock; -}; - -struct iwl_dma_ptr { - dma_addr_t dma; - void *addr; - size_t size; -}; - -/* - * This queue number is required for proper operation - * because the ucode will stop/start the scheduler as - * required. - */ -#define IWL_IPAN_MCAST_QUEUE 8 - -struct iwl_cmd_meta { - /* only for SYNC commands, iff the reply skb is wanted */ - struct iwl_host_cmd *source; - /* - * only for ASYNC commands - * (which is somewhat stupid -- look at iwl-sta.c for instance - * which duplicates a bunch of code because the callback isn't - * invoked for SYNC commands, if it were and its result passed - * through it would be simpler...) - */ - void (*callback)(struct iwl_shared *shrd, - struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt); - - u32 flags; - - DEFINE_DMA_UNMAP_ADDR(mapping); - DEFINE_DMA_UNMAP_LEN(len); -}; - -/* - * Generic queue structure - * - * Contains common data for Rx and Tx queues. - * - * Note the difference between n_bd and n_window: the hardware - * always assumes 256 descriptors, so n_bd is always 256 (unless - * there might be HW changes in the future). For the normal TX - * queues, n_window, which is the size of the software queue data - * is also 256; however, for the command queue, n_window is only - * 32 since we don't need so many commands pending. Since the HW - * still uses 256 BDs for DMA though, n_bd stays 256. As a result, - * the software buffers (in the variables @meta, @txb in struct - * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds - * in the same struct) have 256. - * This means that we end up with the following: - * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | - * SW entries: | 0 | ... | 31 | - * where N is a number between 0 and 7. This means that the SW - * data is a window overlayed over the HW queue. - */ -struct iwl_queue { - int n_bd; /* number of BDs in this queue */ - int write_ptr; /* 1-st empty entry (index) host_w*/ - int read_ptr; /* last used entry (index) host_r*/ - /* use for monitoring and recovering the stuck queue */ - dma_addr_t dma_addr; /* physical addr for BD's */ - int n_window; /* safe queue window */ - u32 id; - int low_mark; /* low watermark, resume queue if free - * space more than this */ - int high_mark; /* high watermark, stop queue if free - * space less than this */ -}; - -/** - * struct iwl_tx_queue - Tx Queue for DMA - * @q: generic Rx/Tx queue descriptor - * @bd: base of circular buffer of TFDs - * @cmd: array of command/TX buffer pointers - * @meta: array of meta data for each command/tx buffer - * @dma_addr_cmd: physical address of cmd/tx buffer array - * @txb: array of per-TFD driver data - * @time_stamp: time (in jiffies) of last read_ptr change - * @need_update: indicates need to update read/write index - * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled - * @sta_id: valid if sched_retry is set - * @tid: valid if sched_retry is set - * - * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame - * descriptors) and required locking structures. - */ -#define TFD_TX_CMD_SLOTS 256 -#define TFD_CMD_SLOTS 32 - -struct iwl_tx_queue { - struct iwl_queue q; - struct iwl_tfd *tfds; - struct iwl_device_cmd **cmd; - struct iwl_cmd_meta *meta; - struct sk_buff **skbs; - unsigned long time_stamp; - u8 need_update; - u8 sched_retry; - u8 active; - u8 swq_id; - - u16 sta_id; - u16 tid; -}; - -/** - * struct iwl_trans_pcie - PCIe transport specific data - * @rxq: all the RX queue data - * @rx_replenish: work that will be called when buffers need to be allocated - * @trans: pointer to the generic transport area - * @scd_base_addr: scheduler sram base address in SRAM - * @scd_bc_tbls: pointer to the byte count table of the scheduler - * @kw: keep warm address - * @ac_to_fifo: to what fifo is a specifc AC mapped ? - * @ac_to_queue: to what tx queue is a specifc AC mapped ? - * @mcast_queue: - * @txq: Tx DMA processing queues - * @txq_ctx_active_msk: what queue is active - * queue_stopped: tracks what queue is stopped - * queue_stop_count: tracks what SW queue is stopped - */ -struct iwl_trans_pcie { - struct iwl_rx_queue rxq; - struct work_struct rx_replenish; - struct iwl_trans *trans; - - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - struct tasklet_struct irq_tasklet; - struct isr_statistics isr_stats; - - u32 inta_mask; - u32 scd_base_addr; - struct iwl_dma_ptr scd_bc_tbls; - struct iwl_dma_ptr kw; - - const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; - const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; - u8 mcast_queue[NUM_IWL_RXON_CTX]; - - struct iwl_tx_queue *txq; - unsigned long txq_ctx_active_msk; -#define IWL_MAX_HW_QUEUES 32 - unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; - atomic_t queue_stop_count[4]; -}; - -#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ - ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) - /***************************************************** * RX ******************************************************/ void iwl_bg_rx_replenish(struct work_struct *data); -void iwl_irq_tasklet(struct iwl_trans *trans); -void iwlagn_rx_replenish(struct iwl_trans *trans); -void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, +void iwl_irq_tasklet(struct iwl_priv *priv); +void iwlagn_rx_replenish(struct iwl_priv *priv); +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); /***************************************************** * ICT ******************************************************/ -int iwl_reset_ict(struct iwl_trans *trans); -void iwl_disable_ict(struct iwl_trans *trans); -int iwl_alloc_isr_ict(struct iwl_trans *trans); -void iwl_free_isr_ict(struct iwl_trans *trans); +int iwl_reset_ict(struct iwl_priv *priv); +void iwl_disable_ict(struct iwl_priv *priv); +int iwl_alloc_isr_ict(struct iwl_priv *priv); +void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); + /***************************************************** * TX / HCMD ******************************************************/ -void iwl_txq_update_write_ptr(struct iwl_trans *trans, - struct iwl_tx_queue *txq); -int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset); -int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); -int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); -int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data); -void iwl_tx_cmd_complete(struct iwl_trans *trans, - struct iwl_rx_mem_buffer *rxb); -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, + int count, int slots_num, u32 id); +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, + u16 len, const void *data); +void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt); -void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id); -int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid); -void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); -void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index); +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, u16 *ssn); -void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, int frame_limit); -void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, - int index); -int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs); -int iwl_queue_space(const struct iwl_queue *q); - -/***************************************************** -* Error handling -******************************************************/ -int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, - char **buf, bool display); -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); -void iwl_dump_csr(struct iwl_trans *trans); - -/***************************************************** -* Helpers -******************************************************/ -static inline void iwl_disable_interrupts(struct iwl_trans *trans) -{ - clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); - - /* disable interrupts from uCode/NIC to host */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); - - /* acknowledge/clear/reset any interrupts still pending - * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(bus(trans), CSR_INT, 0xffffffff); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); -} - -static inline void iwl_enable_interrupts(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &trans->shrd->status); - iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); -} - -/* - * we have 8 bits used like this: - * - * 7 6 5 4 3 2 1 0 - * | | | | | | | | - * | | | | | | +-+-------- AC queue (0-3) - * | | | | | | - * | +-+-+-+-+------------ HW queue ID - * | - * +---------------------- unused - */ -static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) -{ - BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only use 5 bits */ - - txq->swq_id = (hwq << 2) | ac; -} - -static inline void iwl_wake_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (unlikely(!trans->shrd->mac80211_registered)) - return; - - if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) - if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) - ieee80211_wake_queue(trans->shrd->hw, ac); -} - -static inline void iwl_stop_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (unlikely(!trans->shrd->mac80211_registered)) - return; - - if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) - if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) - ieee80211_stop_queue(trans->shrd->hw, ac); -} - -#ifdef ieee80211_stop_queue -#undef ieee80211_stop_queue -#endif - -#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue - -#ifdef ieee80211_wake_queue -#undef ieee80211_wake_queue -#endif - -#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue - -static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, - int txq_id) -{ - set_bit(txq_id, &trans_pcie->txq_ctx_active_msk); -} - -static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie, - int txq_id) -{ - clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk); -} - -static inline int iwl_queue_used(const struct iwl_queue *q, int i) -{ - return q->write_ptr >= q->read_ptr ? - (i >= q->read_ptr && i < q->write_ptr) : - !(i < q->read_ptr && i >= q->write_ptr); -} - -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) -{ - return index & (q->n_window - 1); -} - -#define IWL_TX_FIFO_BK 0 /* shared */ -#define IWL_TX_FIFO_BE 1 -#define IWL_TX_FIFO_VI 2 /* shared */ -#define IWL_TX_FIFO_VO 3 -#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK -#define IWL_TX_FIFO_BE_IPAN 4 -#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI -#define IWL_TX_FIFO_VO_IPAN 5 -/* re-uses the VO FIFO, uCode will properly flush/schedule */ -#define IWL_TX_FIFO_AUX 5 -#define IWL_TX_FIFO_UNUSED -1 - -/* AUX (TX during scan dwell) queue */ -#define IWL_AUX_QUEUE 10 +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 126e5a4cc401..474860290404 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -30,7 +30,8 @@ #include #include -/*TODO: Remove include to iwl-core.h*/ +#include "iwl-dev.h" +#include "iwl-agn.h" #include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" @@ -126,7 +127,7 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q) /** * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) { unsigned long flags; @@ -137,34 +138,34 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, if (q->need_update == 0) goto exit_unlock; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); + iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(trans, + IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } } @@ -177,7 +178,8 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /** * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) +static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, + dma_addr_t dma_addr) { return cpu_to_le32((u32)(dma_addr >> 8)); } @@ -193,12 +195,9 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwlagn_rx_queue_restock(struct iwl_trans *trans) +static void iwlagn_rx_queue_restock(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -215,7 +214,8 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, + rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -224,7 +224,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) /* If the pre-allocated buffer pool is dropping low, schedule to * refill it */ if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish); + queue_work(priv->workqueue, &priv->rx_replenish); /* If we've added more space for the firmware to place data, tell it. @@ -233,7 +233,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_queue_update_write_ptr(trans, rxq); + iwl_rx_queue_update_write_ptr(priv, rxq); } } @@ -245,12 +245,9 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) * Also restock the Rx queue via iwl_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) +static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; struct page *page; @@ -268,21 +265,20 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) if (rxq->free_count > RX_LOW_WATERMARK) gfp_mask |= __GFP_NOWARN; - if (hw_params(trans).rx_page_order > 0) + if (priv->hw_params.rx_page_order > 0) gfp_mask |= __GFP_COMP; /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, - hw_params(trans).rx_page_order); + page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); if (!page) { if (net_ratelimit()) - IWL_DEBUG_INFO(trans, "alloc_pages failed, " - "order: %d\n", - hw_params(trans).rx_page_order); + IWL_DEBUG_INFO(priv, "alloc_pages failed, " + "order: %d\n", + priv->hw_params.rx_page_order); if ((rxq->free_count <= RX_LOW_WATERMARK) && net_ratelimit()) - IWL_CRIT(trans, "Failed to alloc_pages with %s." + IWL_CRIT(priv, "Failed to alloc_pages with %s." "Only %u free buffers remaining.\n", priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", @@ -297,7 +293,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, hw_params(trans).rx_page_order); + __free_pages(page, priv->hw_params.rx_page_order); return; } element = rxq->rx_used.next; @@ -309,8 +305,8 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0, - PAGE_SIZE << hw_params(trans).rx_page_order, + rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); @@ -326,36 +322,35 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) } } -void iwlagn_rx_replenish(struct iwl_trans *trans) +void iwlagn_rx_replenish(struct iwl_priv *priv) { unsigned long flags; - iwlagn_rx_allocate(trans, GFP_KERNEL); + iwlagn_rx_allocate(priv, GFP_KERNEL); - spin_lock_irqsave(&trans->shrd->lock, flags); - iwlagn_rx_queue_restock(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + iwlagn_rx_queue_restock(priv); + spin_unlock_irqrestore(&priv->lock, flags); } -static void iwlagn_rx_replenish_now(struct iwl_trans *trans) +static void iwlagn_rx_replenish_now(struct iwl_priv *priv) { - iwlagn_rx_allocate(trans, GFP_ATOMIC); + iwlagn_rx_allocate(priv, GFP_ATOMIC); - iwlagn_rx_queue_restock(trans); + iwlagn_rx_queue_restock(priv); } void iwl_bg_rx_replenish(struct work_struct *data) { - struct iwl_trans_pcie *trans_pcie = - container_of(data, struct iwl_trans_pcie, rx_replenish); - struct iwl_trans *trans = trans_pcie->trans; + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rx_replenish); - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - mutex_lock(&trans->shrd->mutex); - iwlagn_rx_replenish(trans); - mutex_unlock(&trans->shrd->mutex); + mutex_lock(&priv->mutex); + iwlagn_rx_replenish(priv); + mutex_unlock(&priv->mutex); } /** @@ -365,13 +360,11 @@ void iwl_bg_rx_replenish(struct work_struct *data) * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ -static void iwl_rx_handle(struct iwl_trans *trans) +static void iwl_rx_handle(struct iwl_priv *priv) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; u32 r, i; int reclaim; unsigned long flags; @@ -386,7 +379,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) /* Rx interrupt, but nothing sent from uCode */ if (i == r) - IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); + IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); /* calculate total frames need to be restock after handling RX */ total_empty = r - rxq->write_actual; @@ -411,17 +404,17 @@ static void iwl_rx_handle(struct iwl_trans *trans) rxq->queue[i] = NULL; - dma_unmap_page(bus(trans)->dev, rxb->page_dma, - PAGE_SIZE << hw_params(trans).rx_page_order, + dma_unmap_page(priv->bus->dev, rxb->page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); - IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, + IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv(trans), pkt, len); + trace_iwlwifi_dev_rx(priv, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -437,7 +430,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && (pkt->hdr.cmd != REPLY_TX); - iwl_rx_dispatch(priv(trans), rxb); + iwl_rx_dispatch(priv, rxb); /* * XXX: After here, we should always check rxb->page @@ -449,12 +442,12 @@ static void iwl_rx_handle(struct iwl_trans *trans) if (reclaim) { /* Invoke any callbacks, transfer the buffer to caller, * and fire off the (possibly) blocking - * iwl_trans_send_cmd() + * trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) - iwl_tx_cmd_complete(trans, rxb); + iwl_tx_cmd_complete(priv, rxb); else - IWL_WARN(trans, "Claim null rxb?\n"); + IWL_WARN(priv, "Claim null rxb?\n"); } /* Reuse the page if possible. For notification packets and @@ -462,9 +455,8 @@ static void iwl_rx_handle(struct iwl_trans *trans) * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, - 0, PAGE_SIZE << - hw_params(trans).rx_page_order, + rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, + 0, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; @@ -480,7 +472,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) count++; if (count >= 8) { rxq->read = i; - iwlagn_rx_replenish_now(trans); + iwlagn_rx_replenish_now(priv); count = 0; } } @@ -489,411 +481,13 @@ static void iwl_rx_handle(struct iwl_trans *trans) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwlagn_rx_replenish_now(trans); - else - iwlagn_rx_queue_restock(trans); -} - -static const char * const desc_lookup_text[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT_WDG", - "SYSASSERT", - "FATAL_ERROR", - "BAD_COMMAND", - "HW_ERROR_TUNE_LOCK", - "HW_ERROR_TEMPERATURE", - "ILLEGAL_CHAN_FREQ", - "VCC_NOT_STABLE", - "FH_ERROR", - "NMI_INTERRUPT_HOST", - "NMI_INTERRUPT_ACTION_PT", - "NMI_INTERRUPT_UNKNOWN", - "UCODE_VERSION_MISMATCH", - "HW_ERROR_ABS_LOCK", - "HW_ERROR_CAL_LOCK_FAIL", - "NMI_INTERRUPT_INST_ACTION_PT", - "NMI_INTERRUPT_DATA_ACTION_PT", - "NMI_TRM_HW_ER", - "NMI_INTERRUPT_TRM", - "NMI_INTERRUPT_BREAK_POINT", - "DEBUG_0", - "DEBUG_1", - "DEBUG_2", - "DEBUG_3", -}; - -static struct { char *name; u8 num; } advanced_lookup[] = { - { "NMI_INTERRUPT_WDG", 0x34 }, - { "SYSASSERT", 0x35 }, - { "UCODE_VERSION_MISMATCH", 0x37 }, - { "BAD_COMMAND", 0x38 }, - { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, - { "FATAL_ERROR", 0x3D }, - { "NMI_TRM_HW_ERR", 0x46 }, - { "NMI_INTERRUPT_TRM", 0x4C }, - { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, - { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, - { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, - { "NMI_INTERRUPT_HOST", 0x66 }, - { "NMI_INTERRUPT_ACTION_PT", 0x7C }, - { "NMI_INTERRUPT_UNKNOWN", 0x84 }, - { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, - { "ADVANCED_SYSASSERT", 0 }, -}; - -static const char *desc_lookup(u32 num) -{ - int i; - int max = ARRAY_SIZE(desc_lookup_text); - - if (num < max) - return desc_lookup_text[num]; - - max = ARRAY_SIZE(advanced_lookup) - 1; - for (i = 0; i < max; i++) { - if (advanced_lookup[i].num == num) - break; - } - return advanced_lookup[i].name; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -static void iwl_dump_nic_error_log(struct iwl_trans *trans) -{ - u32 base; - struct iwl_error_event_table table; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - base = priv->device_pointers.error_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_errlog_ptr; - } else { - if (!base) - base = priv->inst_errlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(trans, - "Not valid error log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return; - } - - iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table)); - - if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { - IWL_ERR(trans, "Start IWL Error Log Dump:\n"); - IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", - trans->shrd->status, table.valid); - } - - trans_pcie->isr_stats.err_code = table.error_id; - - trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, - table.data1, table.data2, table.line, - table.blink1, table.blink2, table.ilink1, - table.ilink2, table.bcon_time, table.gp1, - table.gp2, table.gp3, table.ucode_ver, - table.hw_ver, table.brd_ver); - IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id, - desc_lookup(table.error_id)); - IWL_ERR(trans, "0x%08X | uPc\n", table.pc); - IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1); - IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2); - IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1); - IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2); - IWL_ERR(trans, "0x%08X | data1\n", table.data1); - IWL_ERR(trans, "0x%08X | data2\n", table.data2); - IWL_ERR(trans, "0x%08X | line\n", table.line); - IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time); - IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low); - IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi); - IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1); - IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2); - IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3); - IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver); - IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); - IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); - IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); -} - -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -static void iwl_irq_handle_error(struct iwl_trans *trans) -{ - struct iwl_priv *priv = priv(trans); - /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ - if (priv->cfg->internal_wimax_coex && - (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) & - APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) & - APMG_PS_CTRL_VAL_RESET_REQ))) { - /* - * Keep the restart process from trying to send host - * commands by clearing the ready bit. - */ - clear_bit(STATUS_READY, &trans->shrd->status); - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - wake_up_interruptible(&priv->shrd->wait_command_queue); - IWL_ERR(trans, "RF is used by WiMAX\n"); - return; - } - - IWL_ERR(trans, "Loaded firmware version: %s\n", - priv->hw->wiphy->fw_version); - - iwl_dump_nic_error_log(trans); - iwl_dump_csr(trans); - iwl_dump_fh(trans, NULL, false); - iwl_dump_nic_event_log(trans, false, NULL, false); -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) - iwl_print_rx_config_cmd(priv(trans), IWL_RXON_CTX_BSS); -#endif - - iwlagn_fw_error(priv, false); -} - -#define EVENT_START_OFFSET (4 * sizeof(u32)) - -/** - * iwl_print_event_log - Dump error event log to syslog - * - */ -static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, - u32 num_events, u32 mode, - int pos, char **buf, size_t bufsz) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - unsigned long reg_flags; - struct iwl_priv *priv = priv(trans); - - if (num_events == 0) - return pos; - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_evtlog_ptr; - } else { - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (mode == 0) - event_size = 2 * sizeof(u32); + iwlagn_rx_replenish_now(priv); else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags); - iwl_grab_nic_access(bus(trans)); - - /* Set starting address; reads will auto-increment */ - iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr); - rmb(); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); - if (mode == 0) { - /* data, ev */ - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOG:0x%08x:%04u\n", - time, ev); - } else { - trace_iwlwifi_dev_ucode_event(priv, 0, - time, ev); - IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n", - time, ev); - } - } else { - data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - } else { - IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - trace_iwlwifi_dev_ucode_event(priv, time, - data, ev); - } - } - } - - /* Allow device to power down */ - iwl_release_nic_access(bus(trans)); - spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags); - return pos; -} - -/** - * iwl_print_last_event_logs - Dump the newest # of event log to syslog - */ -static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity, - u32 num_wraps, u32 next_entry, - u32 size, u32 mode, - int pos, char **buf, size_t bufsz) -{ - /* - * display the newest DEFAULT_LOG_ENTRIES entries - * i.e the entries just before the next ont that uCode would fill. - */ - if (num_wraps) { - if (next_entry < size) { - pos = iwl_print_event_log(trans, - capacity - (size - next_entry), - size - next_entry, mode, - pos, buf, bufsz); - pos = iwl_print_event_log(trans, 0, - next_entry, mode, - pos, buf, bufsz); - } else - pos = iwl_print_event_log(trans, next_entry - size, - size, mode, pos, buf, bufsz); - } else { - if (next_entry < size) { - pos = iwl_print_event_log(trans, 0, next_entry, - mode, pos, buf, bufsz); - } else { - pos = iwl_print_event_log(trans, next_entry - size, - size, mode, pos, buf, bufsz); - } - } - return pos; -} - -#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) - -int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, - char **buf, bool display) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - u32 size; /* # entries that we'll print */ - u32 logsize; - int pos = 0; - size_t bufsz = 0; - struct iwl_priv *priv = priv(trans); - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - logsize = priv->init_evtlog_size; - if (!base) - base = priv->init_evtlog_ptr; - } else { - logsize = priv->inst_evtlog_size; - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(trans, - "Invalid event log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return -EINVAL; - } - - /* event log header */ - capacity = iwl_read_targ_mem(bus(trans), base); - mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32))); - - if (capacity > logsize) { - IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " - "entries\n", capacity, logsize); - capacity = logsize; - } - - if (next_entry > logsize) { - IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", - next_entry, logsize); - next_entry = logsize; - } - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); - return pos; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#else - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#endif - IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", - size); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - if (full_log) - bufsz = capacity * 48; - else - bufsz = size * 48; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - } - if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) { - /* - * if uCode has wrapped back to top of log, - * start at the oldest entry, - * i.e the next one that uCode would fill. - */ - if (num_wraps) - pos = iwl_print_event_log(trans, next_entry, - capacity - next_entry, mode, - pos, buf, bufsz); - /* (then/else) start at top of log */ - pos = iwl_print_event_log(trans, 0, - next_entry, mode, pos, buf, bufsz); - } else - pos = iwl_print_last_event_logs(trans, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#else - pos = iwl_print_last_event_logs(trans, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#endif - return pos; + iwlagn_rx_queue_restock(priv); } /* tasklet for iwlagn interrupt */ -void iwl_irq_tasklet(struct iwl_trans *trans) +void iwl_irq_tasklet(struct iwl_priv *priv) { u32 inta = 0; u32 handled = 0; @@ -903,11 +497,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) u32 inta_mask; #endif - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, @@ -920,34 +510,33 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(bus(trans), CSR_INT, - trans_pcie->inta | ~trans_pcie->inta_mask); + iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); - inta = trans_pcie->inta; + inta = priv->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { + if (iwl_get_debug_level(priv) & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); - IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", + inta_mask = iwl_read32(priv, CSR_INT_MASK); + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", inta, inta_mask); } #endif - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - /* saved interrupt in inta variable now we can reset trans_pcie->inta */ - trans_pcie->inta = 0; + /* saved interrupt in inta variable now we can reset priv->inta */ + priv->inta = 0; /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(trans, "Hardware error detected. Restarting.\n"); + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(trans); + iwl_disable_interrupts(priv); - isr_stats->hw++; - iwl_irq_handle_error(trans); + priv->isr_stats.hw++; + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -955,18 +544,18 @@ void iwl_irq_tasklet(struct iwl_trans *trans) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); - isr_stats->sch++; + priv->isr_stats.sch++; } /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(trans, "Alive interrupt\n"); - isr_stats->alive++; + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; } } #endif @@ -976,28 +565,26 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); - isr_stats->rfkill++; + priv->isr_stats.rfkill++; /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) { + if (!test_bit(STATUS_ALIVE, &priv->status)) { if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); - iwl_set_hw_rfkill_state(priv(trans), hw_rf_kill); + clear_bit(STATUS_RF_KILL_HW, &priv->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); } handled |= CSR_INT_BIT_RF_KILL; @@ -1005,29 +592,28 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(trans, "Microcode CT kill error detected.\n"); - isr_stats->ctkill++; + IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; handled |= CSR_INT_BIT_CT_KILL; } /* Error detected by uCode */ if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(trans, "Microcode SW error detected. " + IWL_ERR(priv, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); - isr_stats->sw++; - iwl_irq_handle_error(trans); + priv->isr_stats.sw++; + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); - for (i = 0; i < hw_params(trans).max_txq_num; i++) - iwl_txq_update_write_ptr(trans, - &trans_pcie->txq[i]); + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + for (i = 0; i < priv->hw_params.max_txq_num; i++) + iwl_txq_update_write_ptr(priv, &priv->txq[i]); - isr_stats->wakeup++; + priv->isr_stats.wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -1037,16 +623,15 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | CSR_INT_BIT_RX_PERIODIC)) { - IWL_DEBUG_ISR(trans, "Rx interrupt\n"); + IWL_DEBUG_ISR(priv, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(bus(trans), - CSR_INT, CSR_INT_BIT_RX_PERIODIC); + iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the * the device: @@ -1060,9 +645,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - iwl_rx_handle(trans); + iwl_rx_handle(priv); /* * Enable periodic interrupt in 8 msec only if we received @@ -1072,40 +657,40 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); - isr_stats->rx++; + priv->isr_stats.rx++; } /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); - IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); - isr_stats->tx++; + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ - priv(trans)->ucode_write_complete = 1; - wake_up_interruptible(&trans->shrd->wait_command_queue); + priv->ucode_write_complete = 1; + wake_up_interruptible(&priv->wait_command_queue); } if (inta & ~handled) { - IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - isr_stats->unhandled++; + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; } - if (inta & ~(trans_pcie->inta_mask)) { - IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n", - inta & ~trans_pcie->inta_mask); + if (inta & ~(priv->inta_mask)) { + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", + inta & ~priv->inta_mask); } /* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv(trans)); + iwl_enable_rfkill_int(priv); } /****************************************************************************** @@ -1116,21 +701,18 @@ void iwl_irq_tasklet(struct iwl_trans *trans) #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) /* Free dram table */ -void iwl_free_isr_ict(struct iwl_trans *trans) +void iwl_free_isr_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (trans_pcie->ict_tbl_vir) { - dma_free_coherent(bus(trans)->dev, + if (priv->ict_tbl_vir) { + dma_free_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - trans_pcie->ict_tbl_vir, - trans_pcie->ict_tbl_dma); - trans_pcie->ict_tbl_vir = NULL; - memset(&trans_pcie->ict_tbl_dma, 0, - sizeof(trans_pcie->ict_tbl_dma)); - memset(&trans_pcie->aligned_ict_tbl_dma, 0, - sizeof(trans_pcie->aligned_ict_tbl_dma)); + priv->ict_tbl_vir, + priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + memset(&priv->ict_tbl_dma, 0, + sizeof(priv->ict_tbl_dma)); + memset(&priv->aligned_ict_tbl_dma, 0, + sizeof(priv->aligned_ict_tbl_dma)); } } @@ -1138,168 +720,157 @@ void iwl_free_isr_ict(struct iwl_trans *trans) /* allocate dram shared table it is a PAGE_SIZE aligned * also reset all data related to ICT table interrupt. */ -int iwl_alloc_isr_ict(struct iwl_trans *trans) +int iwl_alloc_isr_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); /* allocate shrared data table */ - trans_pcie->ict_tbl_vir = - dma_alloc_coherent(bus(trans)->dev, + priv->ict_tbl_vir = + dma_alloc_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &trans_pcie->ict_tbl_dma, GFP_KERNEL); - if (!trans_pcie->ict_tbl_vir) + &priv->ict_tbl_dma, GFP_KERNEL); + if (!priv->ict_tbl_vir) return -ENOMEM; /* align table to PAGE_SIZE boundary */ - trans_pcie->aligned_ict_tbl_dma = - ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); + priv->aligned_ict_tbl_dma = + ALIGN(priv->ict_tbl_dma, PAGE_SIZE); - IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)trans_pcie->ict_tbl_dma, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); - trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + - (trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma); + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma); - IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", - trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); /* reset table and index to all 0 */ - memset(trans_pcie->ict_tbl_vir, 0, + memset(priv->ict_tbl_vir, 0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - trans_pcie->ict_index = 0; + priv->ict_index = 0; /* add periodic RX interrupt */ - trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; return 0; } /* Device is going up inform it about using ICT interrupt table, * also we need to tell the driver to start using ICT interrupt. */ -int iwl_reset_ict(struct iwl_trans *trans) +int iwl_reset_ict(struct iwl_priv *priv) { u32 val; unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->ict_tbl_vir) + if (!priv->ict_tbl_vir) return 0; - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); - memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " + IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " "aligned dma address %Lx\n", val, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma); + (unsigned long long)priv->aligned_ict_tbl_dma); - iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); - trans_pcie->use_ict = true; - trans_pcie->ict_index = 0; - iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); - iwl_enable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); + priv->use_ict = true; + priv->ict_index = 0; + iwl_write32(priv, CSR_INT, priv->inta_mask); + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } /* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_trans *trans) +void iwl_disable_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; - spin_lock_irqsave(&trans->shrd->lock, flags); - trans_pcie->use_ict = false; - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + priv->use_ict = false; + spin_unlock_irqrestore(&priv->lock, flags); } static irqreturn_t iwl_isr(int irq, void *data) { - struct iwl_trans *trans = data; - struct iwl_trans_pcie *trans_pcie; + struct iwl_priv *priv = data; u32 inta, inta_mask; unsigned long flags; #ifdef CONFIG_IWLWIFI_DEBUG u32 inta_fh; #endif - if (!trans) + if (!priv) return IRQ_NONE; - trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl_read32(bus(trans), CSR_INT); + inta = iwl_read32(priv, CSR_INT); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ if (!inta) { - IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared. It might have already raised * an interrupt */ - IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); goto unplugged; } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); } #endif - trans_pcie->inta |= inta; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) + iwl_enable_interrupts(priv); unplugged: - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } @@ -1313,53 +884,50 @@ static irqreturn_t iwl_isr(int irq, void *data) */ irqreturn_t iwl_isr_ict(int irq, void *data) { - struct iwl_trans *trans = data; - struct iwl_trans_pcie *trans_pcie; + struct iwl_priv *priv = data; u32 inta, inta_mask; u32 val = 0; unsigned long flags; - if (!trans) + if (!priv) return IRQ_NONE; - trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - /* dram interrupt table not set yet, * use legacy interrupt. */ - if (!trans_pcie->use_ict) + if (!priv->use_ict) return iwl_isr(irq, data); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) { - IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); + if (!priv->ict_tbl[priv->ict_index]) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } /* read all entries that not 0 start with ict_index */ - while (trans_pcie->ict_tbl[trans_pcie->ict_index]) { + while (priv->ict_tbl[priv->ict_index]) { - val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); - IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", - trans_pcie->ict_index, + val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); + IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", + priv->ict_index, le32_to_cpu( - trans_pcie->ict_tbl[trans_pcie->ict_index])); - trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; - trans_pcie->ict_index = - iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); + priv->ict_tbl[priv->ict_index])); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + ICT_COUNT); } @@ -1378,35 +946,34 @@ irqreturn_t iwl_isr_ict(int irq, void *data) val |= 0x8000; inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", inta, inta_mask, val); - inta &= trans_pcie->inta_mask; - trans_pcie->inta |= inta; + inta &= priv->inta_mask; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) { + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. */ - iwl_enable_interrupts(trans); + iwl_enable_interrupts(priv); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index ca686dbf5893..a6b2b1db0b1d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -29,30 +29,23 @@ #include #include #include +#include -/* TODO: remove include to iwl-dev.h */ +#include "iwl-agn.h" #include "iwl-dev.h" -#include "iwl-debug.h" -#include "iwl-csr.h" -#include "iwl-prph.h" +#include "iwl-core.h" #include "iwl-io.h" -#include "iwl-agn-hw.h" #include "iwl-helpers.h" #include "iwl-trans-int-pcie.h" -#define IWL_TX_CRC_SIZE 4 -#define IWL_TX_DELIMITER_SIZE 4 - /** * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt) { - struct iwlagn_scd_bc_tbl *scd_bc_tbl; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int write_ptr = txq->q.write_ptr; int txq_id = txq->q.id; u8 sec_ctl = 0; @@ -60,8 +53,6 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; __le16 bc_ent; - scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; @@ -91,7 +82,7 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, /** * iwl_txq_update_write_ptr - Send new write index to hardware */ -void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) { u32 reg = 0; int txq_id = txq->q.id; @@ -99,28 +90,28 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->status)) { /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(trans, + IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup," " GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return; } - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); /* @@ -129,7 +120,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } txq->need_update = 0; @@ -174,7 +165,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) return tfd->num_tbs & 0x1f; } -static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, +static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { int i; @@ -184,56 +175,56 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, num_tbs = iwl_tfd_get_num_tbs(tfd); if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); /* @todo issue fatal error, it is quite serious situation */ return; } /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(bus(trans)->dev, + dma_unmap_single(priv->bus->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } /** * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @trans - transport private data + * @priv - driver private data * @txq - tx queue * @index - the index of the TFD to be freed * * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, int index) { struct iwl_tfd *tfd_tmp = txq->tfds; - iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], + iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], DMA_TO_DEVICE); /* free SKB */ - if (txq->skbs) { + if (txq->txb) { struct sk_buff *skb; - skb = txq->skbs[index]; + skb = txq->txb[index].skb; /* can be called from irqs-disabled context */ if (skb) { dev_kfree_skb_any(skb); - txq->skbs[index] = NULL; + txq->txb[index].skb = NULL; } } } -int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset) @@ -253,7 +244,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, /* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(trans, "Error can not send more than %d chunks\n", + IWL_ERR(priv, "Error can not send more than %d chunks\n", IWL_NUM_OF_TBS); return -EINVAL; } @@ -262,7 +253,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, return -EINVAL; if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(trans, "Unaligned address = %llx\n", + IWL_ERR(priv, "Unaligned address = %llx\n", (unsigned long long)addr); iwl_tfd_set_tb(tfd, num_tbs, addr, len); @@ -311,7 +302,8 @@ int iwl_queue_space(const struct iwl_queue *q) /** * iwl_queue_init - Initialize queue's high/low-water and read/write indexes */ -int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, + int count, int slots_num, u32 id) { q->n_bd = count; q->n_window = slots_num; @@ -340,12 +332,16 @@ int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) return 0; } -static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too. + * Add a declaration to make sparse happy */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); + +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int txq_id = txq->q.id; int read_ptr = txq->q.read_ptr; u8 sta_id = 0; @@ -353,7 +349,7 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != trans->shrd->cmd_queue) + if (txq_id != priv->cmd_queue) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -364,61 +360,56 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; } -static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, +static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, u16 txq_id) { u32 tbl_dw_addr; u32 tbl_dw; u16 scd_q2ratid; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; - tbl_dw_addr = trans_pcie->scd_base_addr + + tbl_dw_addr = priv->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); return 0; } -static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) +static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(bus(trans), + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } -void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) { - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); } -void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id = txq->q.id; - int active = - test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; + int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -426,75 +417,55 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n", + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, - u8 ctx, u16 tid) -{ - const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx]; - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return ac_to_fifo[tid_to_ac[tid]]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, int frame_limit) +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit) { int tx_fifo, txq_id, ssn_idx; u16 ra_tid; unsigned long flags; struct iwl_tid_data *tid_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) return; - if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) + if (WARN_ON(tid >= MAX_TID_COUNT)) return; - tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid); - if (WARN_ON(tx_fifo < 0)) { - IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); - return; - } - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - tid_data = &trans->shrd->tid_data[sta_id][tid]; + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + tx_fifo = tid_data->agg.tx_fifo; + spin_unlock_irqrestore(&priv->sta_lock, flags); ra_tid = BUILD_RAxTID(sta_id, tid); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Stop this Tx queue before configuring it */ - iwlagn_tx_queue_stop_scheduler(trans, txq_id); + iwlagn_tx_queue_stop_scheduler(priv, txq_id); /* Map receiver-address / traffic-ID to this queue */ - iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); + iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << @@ -504,158 +475,40 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], - tx_fifo, 1); - - trans_pcie->txq[txq_id].sta_id = sta_id; - trans_pcie->txq[txq_id].tid = tid; + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } -/* - * Find first available (lowest unused) Tx Queue, mark it "active". - * Called only when finding queue for aggregation. - * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) - */ -static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int txq_id; - - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) - if (!test_and_set_bit(txq_id, - &trans_pcie->txq_ctx_active_msk)) - return txq_id; - return -1; -} - -int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, u16 *ssn) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tid_data *tid_data; - unsigned long flags; - int txq_id; - - txq_id = iwlagn_txq_ctx_activate_free(trans); - if (txq_id == -1) { - IWL_ERR(trans, "No free aggregation queue available\n"); - return -ENXIO; - } - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - tid_data = &trans->shrd->tid_data[sta_id][tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; - iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id); - - tid_data = &trans->shrd->tid_data[sta_id][tid]; - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(trans, "HW queue is empty\n"); - tid_data->agg.state = IWL_AGG_ON; - iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); - } else { - IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW" - "queue\n", tid_data->tfds_in_queue); - tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; - } - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); - - return 0; -} - -void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwlagn_tx_queue_stop_scheduler(trans, txq_id); - - iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); - - trans_pcie->txq[txq_id].q.read_ptr = 0; - trans_pcie->txq[txq_id].q.write_ptr = 0; - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl_trans_set_wr_ptrs(trans, txq_id, 0); - - iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(trans_pcie, txq_id); - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); -} - -int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; - int read_ptr, write_ptr; - struct iwl_tid_data *tid_data; - int txq_id; - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - - tid_data = &trans->shrd->tid_data[sta_id][tid]; - txq_id = tid_data->agg.txq_id; - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(trans).num_ampdu_queues <= txq_id)) { - IWL_ERR(trans, + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_ERR(priv, "queue number out of range: %d, must be %d to %d\n", txq_id, IWLAGN_FIRST_AMPDU_QUEUE, IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(trans).num_ampdu_queues - 1); - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + priv->cfg->base_params->num_of_ampdu_queues - 1); return -EINVAL; } - switch (trans->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* - * This can happen if the peer stops aggregation - * again before we've had a chance to drain the - * queue we selected previously, i.e. before the - * session was really started completely. - */ - IWL_DEBUG_HT(trans, "AGG stop before setup done\n"); - goto turn_off; - case IWL_AGG_ON: - break; - default: - IWL_WARN(trans, "Stopping AGG while state not ON" - "or starting\n"); - } + iwlagn_tx_queue_stop_scheduler(priv, txq_id); - write_ptr = trans_pcie->txq[txq_id].q.write_ptr; - read_ptr = trans_pcie->txq[txq_id].q.read_ptr; + iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); - /* The queue is not empty */ - if (write_ptr != read_ptr) { - IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n"); - trans->shrd->tid_data[sta_id][tid].agg.state = - IWL_EMPTYING_HW_QUEUE_DELBA; - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); - return 0; - } - - IWL_DEBUG_HT(trans, "HW queue is empty\n"); -turn_off: - trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; - - /* do not restore/save irqs */ - spin_unlock(&trans->shrd->sta_lock); - spin_lock(&trans->shrd->lock); - - iwl_trans_pcie_txq_agg_disable(trans, txq_id); - - spin_unlock_irqrestore(&trans->shrd->lock, flags); + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); + iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); return 0; } @@ -671,10 +524,9 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -692,14 +544,14 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) int trace_idx; #endif - if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { - IWL_WARN(trans, "fw recovery, no hcmd send\n"); + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_WARN(priv, "fw recovery, no hcmd send\n"); return -EIO; } - if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) && + if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n"); + IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); return -EIO; } @@ -732,22 +584,22 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; - if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) { - IWL_WARN(trans, "Not sending command - %s KILL\n", - iwl_is_rfkill(trans->shrd) ? "RF" : "CT"); + if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { + IWL_WARN(priv, "Not sending command - %s KILL\n", + iwl_is_rfkill(priv) ? "RF" : "CT"); return -EIO; } - spin_lock_irqsave(&trans->hcmd_lock, flags); + spin_lock_irqsave(&priv->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); - IWL_ERR(trans, "No space in command queue\n"); - is_ct_kill = iwl_check_for_ct_kill(priv(trans)); + IWL_ERR(priv, "No space in command queue\n"); + is_ct_kill = iwl_check_for_ct_kill(priv); if (!is_ct_kill) { - IWL_ERR(trans, "Restarting adapter queue is full\n"); - iwlagn_fw_error(priv(trans), false); + IWL_ERR(priv, "Restarting adapter due to queue full\n"); + iwlagn_fw_error(priv, false); } return -ENOSPC; } @@ -766,9 +618,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = - cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) | - INDEX_TO_SEQ(q->write_ptr)); + out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | + INDEX_TO_SEQ(q->write_ptr)); /* and copy the data that needs to be copied */ @@ -782,16 +633,16 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) cmd_dest += cmd->len[i]; } - IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, " + IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, - q->write_ptr, idx, trans->shrd->cmd_queue); + q->write_ptr, idx, priv->cmd_queue); - phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -799,8 +650,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, copy_size); - iwlagn_txq_attach_buf_to_tfd(trans, txq, - phys_addr, copy_size, 1); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[0] = &out_cmd->hdr; trace_lens[0] = copy_size; @@ -812,18 +662,17 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(bus(trans)->dev, - (void *)cmd->data[i], + phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(bus(trans)->dev, phys_addr)) { - iwlagn_unmap_tfd(trans, out_meta, + if (dma_mapping_error(priv->bus->dev, phys_addr)) { + iwlagn_unmap_tfd(priv, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } - iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, cmd->len[i], 0); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[trace_idx] = cmd->data[i]; @@ -839,7 +688,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* check that tracing gets all possible blocks */ BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING - trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags, + trace_iwlwifi_dev_hcmd(priv, cmd->flags, trace_bufs[0], trace_lens[0], trace_bufs[1], trace_lens[1], trace_bufs[2], trace_lens[2]); @@ -847,10 +696,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(trans, txq); + iwl_txq_update_write_ptr(priv, txq); out: - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); return idx; } @@ -861,16 +710,14 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) * need to be reclaimed. As result, some free space forms. If there is * enough free space (> low mark), wake the stack that feeds us. */ -static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, - int idx) +static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; int nfreed = 0; if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { - IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " + IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " "index %d is out of range [0-%d] %d %d.\n", __func__, txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr); return; @@ -880,9 +727,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (nfreed++ > 0) { - IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx, + IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, q->write_ptr, q->read_ptr); - iwlagn_fw_error(priv(trans), false); + iwlagn_fw_error(priv, false); } } @@ -896,7 +743,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) +void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -905,19 +752,18 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) int cmd_index; struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != trans->shrd->cmd_queue, + if (WARN(txq_id != priv->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, trans->shrd->cmd_queue, sequence, - trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr, - trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) { - iwl_print_hex_error(trans, pkt, 32); + txq_id, priv->cmd_queue, sequence, + priv->txq[priv->cmd_queue].q.read_ptr, + priv->txq[priv->cmd_queue].q.write_ptr)) { + iwl_print_hex_error(priv, pkt, 32); return; } @@ -925,40 +771,121 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], - DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { meta->source->reply_page = (unsigned long)rxb_addr(rxb); rxb->page = NULL; } else if (meta->callback) - meta->callback(trans->shrd, cmd, pkt); + meta->callback(priv, cmd, pkt); - spin_lock_irqsave(&trans->hcmd_lock, flags); + spin_lock_irqsave(&priv->hcmd_lock, flags); - iwl_hcmd_queue_reclaim(trans, txq_id, index); + iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); - wake_up_interruptible(&trans->shrd->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } meta->flags = 0; - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); +} + +const char *get_cmd_string(u8 cmd) +{ + switch (cmd) { + IWL_CMD(REPLY_ALIVE); + IWL_CMD(REPLY_ERROR); + IWL_CMD(REPLY_RXON); + IWL_CMD(REPLY_RXON_ASSOC); + IWL_CMD(REPLY_QOS_PARAM); + IWL_CMD(REPLY_RXON_TIMING); + IWL_CMD(REPLY_ADD_STA); + IWL_CMD(REPLY_REMOVE_STA); + IWL_CMD(REPLY_REMOVE_ALL_STA); + IWL_CMD(REPLY_TXFIFO_FLUSH); + IWL_CMD(REPLY_WEPKEY); + IWL_CMD(REPLY_TX); + IWL_CMD(REPLY_LEDS_CMD); + IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); + IWL_CMD(COEX_PRIORITY_TABLE_CMD); + IWL_CMD(COEX_MEDIUM_NOTIFICATION); + IWL_CMD(COEX_EVENT_CMD); + IWL_CMD(REPLY_QUIET_CMD); + IWL_CMD(REPLY_CHANNEL_SWITCH); + IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); + IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); + IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); + IWL_CMD(POWER_TABLE_CMD); + IWL_CMD(PM_SLEEP_NOTIFICATION); + IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); + IWL_CMD(REPLY_SCAN_CMD); + IWL_CMD(REPLY_SCAN_ABORT_CMD); + IWL_CMD(SCAN_START_NOTIFICATION); + IWL_CMD(SCAN_RESULTS_NOTIFICATION); + IWL_CMD(SCAN_COMPLETE_NOTIFICATION); + IWL_CMD(BEACON_NOTIFICATION); + IWL_CMD(REPLY_TX_BEACON); + IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); + IWL_CMD(QUIET_NOTIFICATION); + IWL_CMD(REPLY_TX_PWR_TABLE_CMD); + IWL_CMD(MEASURE_ABORT_NOTIFICATION); + IWL_CMD(REPLY_BT_CONFIG); + IWL_CMD(REPLY_STATISTICS_CMD); + IWL_CMD(STATISTICS_NOTIFICATION); + IWL_CMD(REPLY_CARD_STATE_CMD); + IWL_CMD(CARD_STATE_NOTIFICATION); + IWL_CMD(MISSED_BEACONS_NOTIFICATION); + IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); + IWL_CMD(SENSITIVITY_CMD); + IWL_CMD(REPLY_PHY_CALIBRATION_CMD); + IWL_CMD(REPLY_RX_PHY_CMD); + IWL_CMD(REPLY_RX_MPDU_CMD); + IWL_CMD(REPLY_RX); + IWL_CMD(REPLY_COMPRESSED_BA); + IWL_CMD(CALIBRATION_CFG_CMD); + IWL_CMD(CALIBRATION_RES_NOTIFICATION); + IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); + IWL_CMD(REPLY_TX_POWER_DBM_CMD); + IWL_CMD(TEMPERATURE_NOTIFICATION); + IWL_CMD(TX_ANT_CONFIGURATION_CMD); + IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); + IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); + IWL_CMD(REPLY_BT_COEX_PROT_ENV); + IWL_CMD(REPLY_WIPAN_PARAMS); + IWL_CMD(REPLY_WIPAN_RXON); + IWL_CMD(REPLY_WIPAN_RXON_TIMING); + IWL_CMD(REPLY_WIPAN_RXON_ASSOC); + IWL_CMD(REPLY_WIPAN_QOS_PARAM); + IWL_CMD(REPLY_WIPAN_WEPKEY); + IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); + IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); + IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); + IWL_CMD(REPLY_WOWLAN_PATTERNS); + IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER); + IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS); + IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); + IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); + IWL_CMD(REPLY_WOWLAN_GET_STATUS); + default: + return "UNKNOWN"; + + } } #define HOST_COMPLETE_TIMEOUT (2 * HZ) -static void iwl_generic_cmd_callback(struct iwl_shared *shrd, +static void iwl_generic_cmd_callback(struct iwl_priv *priv, struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt) { if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(shrd->trans, "Bad return from %s (0x%08X)\n", + IWL_ERR(priv, "Bad return from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); return; } @@ -967,17 +894,17 @@ static void iwl_generic_cmd_callback(struct iwl_shared *shrd, switch (cmd->hdr.cmd) { case REPLY_TX_LINK_QUALITY_CMD: case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(shrd->trans, "back from %s (0x%08X)\n", + IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); break; default: - IWL_DEBUG_HC(shrd->trans, "back from %s (0x%08X)\n", + IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); } #endif } -static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int ret; @@ -989,78 +916,77 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (!cmd->callback) cmd->callback = iwl_generic_cmd_callback; - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EBUSY; - ret = iwl_enqueue_hcmd(trans, cmd); + ret = iwl_enqueue_hcmd(priv, cmd); if (ret < 0) { - IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } return 0; } -static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int cmd_idx; int ret; - lockdep_assert_held(&trans->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* A synchronous command can not have a callback set. */ if (WARN_ON(cmd->callback)) return -EINVAL; - IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", + IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", + set_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); - cmd_idx = iwl_enqueue_hcmd(trans, cmd); + cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } - ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + !test_bit(STATUS_HCMD_ACTIVE, &priv->status), HOST_COMPLETE_TIMEOUT); if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { - IWL_ERR(trans, + if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { + IWL_ERR(priv, "Error sending %s: time out after %dms.\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command" + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" "%s\n", get_cmd_string(cmd->id)); ret = -ETIMEDOUT; goto cancel; } } - if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) { - IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n", + if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); ret = -ECANCELED; goto fail; } - if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { - IWL_ERR(trans, "Command %s failed: FW Error\n", + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_ERR(priv, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); ret = -EIO; goto fail; } if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { - IWL_ERR(trans, "Error: Response NULL in '%s'\n", + IWL_ERR(priv, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; goto cancel; @@ -1076,28 +1002,28 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) * in later, it will possibly set an invalid * address (cmd->meta.source). */ - trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= + priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: if (cmd->reply_page) { - iwl_free_pages(trans->shrd, cmd->reply_page); + iwl_free_pages(priv, cmd->reply_page); cmd->reply_page = 0; } return ret; } -int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { if (cmd->flags & CMD_ASYNC) - return iwl_send_cmd_async(trans, cmd); + return iwl_send_cmd_async(priv, cmd); - return iwl_send_cmd_sync(trans, cmd); + return iwl_send_cmd_sync(priv, cmd); } -int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, - u16 len, const void *data) +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data) { struct iwl_host_cmd cmd = { .id = id, @@ -1106,53 +1032,5 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, .flags = flags, }; - return iwl_trans_pcie_send_cmd(trans, &cmd); -} - -/* Frees buffers until index _not_ inclusive */ -int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - struct iwl_queue *q = &txq->q; - int last_to_free; - int freed = 0; - - /*Since we free until index _not_ inclusive, the one before index is - * the last we will free. This one must be used */ - last_to_free = iwl_queue_dec_wrap(index, q->n_bd); - - if ((index >= q->n_bd) || - (iwl_queue_used(q, last_to_free) == 0)) { - IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " - "last_to_free %d is out of range [0-%d] %d %d.\n", - __func__, txq_id, last_to_free, q->n_bd, - q->write_ptr, q->read_ptr); - return 0; - } - - IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id, - q->read_ptr, index); - - if (WARN_ON(!skb_queue_empty(skbs))) - return 0; - - for (; - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL)) - continue; - - __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]); - - txq->skbs[txq->q.read_ptr] = NULL; - - iwlagn_txq_inval_byte_cnt_tbl(trans, txq); - - iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); - freed++; - } - return freed; + return iwl_send_cmd(priv, &cmd); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c index b2e89077c684..3001bfb46e25 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -60,27 +60,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#include -#include -#include -#include - +#include "iwl-dev.h" #include "iwl-trans.h" +#include "iwl-core.h" +#include "iwl-helpers.h" #include "iwl-trans-int-pcie.h" -#include "iwl-csr.h" -#include "iwl-prph.h" -#include "iwl-shared.h" -#include "iwl-eeprom.h" -#include "iwl-agn-hw.h" +/*TODO remove uneeded includes when the transport layer tx_free will be here */ +#include "iwl-agn.h" +#include "iwl-core.h" -static int iwl_trans_rx_alloc(struct iwl_trans *trans) +static int iwl_trans_rx_alloc(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct device *dev = bus(trans)->dev; + struct iwl_rx_queue *rxq = &priv->rxq; + struct device *dev = priv->bus->dev; - memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); + memset(&priv->rxq, 0, sizeof(priv->rxq)); spin_lock_init(&rxq->lock); INIT_LIST_HEAD(&rxq->rx_free); @@ -114,11 +108,9 @@ static int iwl_trans_rx_alloc(struct iwl_trans *trans) return -ENOMEM; } -static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) +static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; int i; /* Fill the rx_used queue with _all_ of the Rx buffers */ @@ -126,18 +118,17 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, - PAGE_SIZE << hw_params(trans).rx_page_order, + dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, - hw_params(trans).rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); } } -static void iwl_trans_rx_hw_init(struct iwl_trans *trans, +static void iwl_trans_rx_hw_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { u32 rb_size; @@ -152,17 +143,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; /* Stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* Reset driver's Rx queue write index */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4); /* Enable Rx DMA @@ -173,7 +164,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, * RB timeout 0x10 * 256 RBDs */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | @@ -183,20 +174,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static int iwl_rx_init(struct iwl_trans *trans) +static int iwl_rx_init(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - + struct iwl_rx_queue *rxq = &priv->rxq; int i, err; unsigned long flags; if (!rxq->bd) { - err = iwl_trans_rx_alloc(trans); + err = iwl_trans_rx_alloc(priv); if (err) return err; } @@ -205,7 +193,7 @@ static int iwl_rx_init(struct iwl_trans *trans) INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); - iwl_trans_rxq_free_rx_bufs(trans); + iwl_trans_rxq_free_rx_bufs(priv); for (i = 0; i < RX_QUEUE_SIZE; i++) rxq->queue[i] = NULL; @@ -217,68 +205,65 @@ static int iwl_rx_init(struct iwl_trans *trans) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); - iwlagn_rx_replenish(trans); + iwlagn_rx_replenish(priv); - iwl_trans_rx_hw_init(trans, rxq); + iwl_trans_rx_hw_init(priv, rxq); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(trans, rxq); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + iwl_rx_queue_update_write_ptr(priv, rxq); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } -static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) +static void iwl_trans_rx_free(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - + struct iwl_rx_queue *rxq = &priv->rxq; unsigned long flags; /*if rxq->bd is NULL, it means that nothing has been allocated, * exit now */ if (!rxq->bd) { - IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); + IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); return; } spin_lock_irqsave(&rxq->lock, flags); - iwl_trans_rxq_free_rx_bufs(trans); + iwl_trans_rxq_free_rx_bufs(priv); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(bus(trans)->dev, + dma_free_coherent(priv->bus->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else - IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); + IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); rxq->rb_stts = NULL; } -static int iwl_trans_rx_stop(struct iwl_trans *trans) +static int iwl_trans_rx_stop(struct iwl_priv *priv) { /* stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); } -static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, +static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr, size_t size) { if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, + ptr->addr = dma_alloc_coherent(priv->bus->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -286,24 +271,23 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, return 0; } -static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, +static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr) { if (unlikely(!ptr->addr)) return; - dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } -static int iwl_trans_txq_alloc(struct iwl_trans *trans, - struct iwl_tx_queue *txq, int slots_num, - u32 txq_id) +static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) { - size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; + size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; int i; - if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) + if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) return -EINVAL; txq->q.n_window = slots_num; @@ -316,46 +300,45 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, if (!txq->meta || !txq->cmd) goto error; - if (txq_id == trans->shrd->cmd_queue) - for (i = 0; i < slots_num; i++) { - txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), - GFP_KERNEL); - if (!txq->cmd[i]) - goto error; - } + for (i = 0; i < slots_num; i++) { + txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), + GFP_KERNEL); + if (!txq->cmd[i]) + goto error; + } /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (txq_id != trans->shrd->cmd_queue) { - txq->skbs = kzalloc(sizeof(txq->skbs[0]) * + if (txq_id != priv->cmd_queue) { + txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); - if (!txq->skbs) { - IWL_ERR(trans, "kmalloc for auxiliary BD " + if (!txq->txb) { + IWL_ERR(priv, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } } else { - txq->skbs = NULL; + txq->txb = NULL; } /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, - &txq->q.dma_addr, GFP_KERNEL); + txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr, + GFP_KERNEL); if (!txq->tfds) { - IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); + IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); goto error; } txq->q.id = txq_id; return 0; error: - kfree(txq->skbs); - txq->skbs = NULL; + kfree(txq->txb); + txq->txb = NULL; /* since txq->cmd has been zeroed, * all non allocated cmd[i] will be NULL */ - if (txq->cmd && txq_id == trans->shrd->cmd_queue) + if (txq->cmd) for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); kfree(txq->meta); @@ -367,7 +350,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, } -static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, +static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { int ret; @@ -388,7 +371,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ - ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, + ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); if (ret) return ret; @@ -397,7 +380,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); return 0; @@ -406,10 +389,9 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, /** * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's */ -static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) +static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; if (!q->n_bd) @@ -417,7 +399,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) while (q->write_ptr != q->read_ptr) { /* The read_ptr needs to bound by q->n_window */ - iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr)); + iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -430,33 +412,30 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) +static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - struct device *dev = bus(trans)->dev; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct device *dev = priv->bus->dev; int i; if (WARN_ON(!txq)) return; - iwl_tx_queue_unmap(trans, txq_id); + iwl_tx_queue_unmap(priv, txq_id); /* De-alloc array of command/tx buffers */ - - if (txq_id == trans->shrd->cmd_queue) - for (i = 0; i < txq->q.n_window; i++) - kfree(txq->cmd[i]); + for (i = 0; i < txq->q.n_window; i++) + kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { - dma_free_coherent(dev, sizeof(struct iwl_tfd) * + dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); } /* De-alloc array of per-TFD driver data */ - kfree(txq->skbs); - txq->skbs = NULL; + kfree(txq->txb); + txq->txb = NULL; /* deallocate arrays */ kfree(txq->cmd); @@ -473,24 +452,22 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) * * Destroy all TX DMA queues and structures */ -static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) +static void iwl_trans_tx_free(struct iwl_priv *priv) { int txq_id; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Tx queues */ - if (trans_pcie->txq) { - for (txq_id = 0; - txq_id < hw_params(trans).max_txq_num; txq_id++) - iwl_tx_queue_free(trans, txq_id); + if (priv->txq) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + iwl_tx_queue_free(priv, txq_id); } - kfree(trans_pcie->txq); - trans_pcie->txq = NULL; + kfree(priv->txq); + priv->txq = NULL; - iwlagn_free_dma_ptr(trans, &trans_pcie->kw); + iwlagn_free_dma_ptr(priv, &priv->kw); - iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); + iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); } /** @@ -500,52 +477,48 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) * @param priv * @return error code */ -static int iwl_trans_tx_alloc(struct iwl_trans *trans) +static int iwl_trans_tx_alloc(struct iwl_priv *priv) { int ret; int txq_id, slots_num; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * - sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ - if (WARN_ON(trans_pcie->txq)) { + if (WARN_ON(priv->txq)) { ret = -EINVAL; goto error; } - ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, - scd_bc_tbls_size); + ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, + priv->hw_params.scd_bc_tbls_size); if (ret) { - IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); + IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); goto error; } /* Alloc keep-warm buffer */ - ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); + ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); if (ret) { - IWL_ERR(trans, "Keep Warm allocation failed\n"); + IWL_ERR(priv, "Keep Warm allocation failed\n"); goto error; } - trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) * - hw_params(trans).max_txq_num, GFP_KERNEL); - if (!trans_pcie->txq) { - IWL_ERR(trans, "Not enough memory for txq\n"); + priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * + priv->cfg->base_params->num_of_queues, GFP_KERNEL); + if (!priv->txq) { + IWL_ERR(priv, "Not enough memory for txq\n"); ret = ENOMEM; goto error; } /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); + ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, + txq_id); if (ret) { - IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id); goto error; } } @@ -553,44 +526,42 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) return 0; error: - iwl_trans_pcie_tx_free(trans); + trans_tx_free(&priv->trans); return ret; } -static int iwl_tx_init(struct iwl_trans *trans) +static int iwl_tx_init(struct iwl_priv *priv) { int ret; int txq_id, slots_num; unsigned long flags; bool alloc = false; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->txq) { - ret = iwl_trans_tx_alloc(trans); + if (!priv->txq) { + ret = iwl_trans_tx_alloc(priv); if (ret) goto error; alloc = true; } - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(bus(trans), SCD_TXFACT, 0); + iwl_write_prph(priv, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, - trans_pcie->kw.dma >> 4); + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); + ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, + txq_id); if (ret) { - IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); goto error; } } @@ -599,59 +570,58 @@ static int iwl_tx_init(struct iwl_trans *trans) error: /*Upon error, free only if we allocated something */ if (alloc) - iwl_trans_pcie_tx_free(trans); + trans_tx_free(&priv->trans); return ret; } -static void iwl_set_pwr_vmain(struct iwl_trans *trans) +static void iwl_set_pwr_vmain(struct iwl_priv *priv) { /* * (for documentation purposes) * to set power to V_AUX, do: if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); */ - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); } -static int iwl_nic_init(struct iwl_trans *trans) +static int iwl_nic_init(struct iwl_priv *priv) { unsigned long flags; /* nic_init */ - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_apm_init(priv(trans)); + spin_lock_irqsave(&priv->lock, flags); + iwl_apm_init(priv); /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, - IWL_HOST_INT_CALIB_TIMEOUT_DEF); + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - iwl_set_pwr_vmain(trans); + iwl_set_pwr_vmain(priv); - iwl_nic_config(priv(trans)); + priv->cfg->lib->nic_config(priv); /* Allocate the RX queue, or reset if it is already allocated */ - iwl_rx_init(trans); + iwl_rx_init(priv); /* Allocate or reset and init all Tx and Command queues */ - if (iwl_tx_init(trans)) + if (iwl_tx_init(priv)) return -ENOMEM; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* enable shadow regs in HW */ - iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); } - set_bit(STATUS_INIT, &trans->shrd->status); + set_bit(STATUS_INIT, &priv->status); return 0; } @@ -659,39 +629,39 @@ static int iwl_nic_init(struct iwl_trans *trans) #define HW_READY_TIMEOUT (50) /* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_set_hw_ready(struct iwl_trans *trans) +static int iwl_set_hw_ready(struct iwl_priv *priv) { int ret; - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); - IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); return ret; } /* Note: returns standard 0/-ERROR code */ -static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) +static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) { int ret; - IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); + IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n"); - ret = iwl_set_hw_ready(trans); + ret = iwl_set_hw_ready(priv); if (ret >= 0) return 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); @@ -699,186 +669,153 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) return ret; /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(trans); + ret = iwl_set_hw_ready(priv); if (ret >= 0) return 0; return ret; } -#define IWL_AC_UNSET -1 - -struct queue_to_fifo_ac { - s8 fifo, ac; -}; - -static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, -}; - -static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_BE_IPAN, 2, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, -}; - -static const u8 iwlagn_bss_ac_to_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, -}; -static const u8 iwlagn_bss_ac_to_queue[] = { - 0, 1, 2, 3, -}; -static const u8 iwlagn_pan_ac_to_fifo[] = { - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_BK_IPAN, -}; -static const u8 iwlagn_pan_ac_to_queue[] = { - 7, 6, 5, 4, -}; - -static int iwl_trans_pcie_start_device(struct iwl_trans *trans) +static int iwl_trans_start_device(struct iwl_priv *priv) { int ret; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; - trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; - trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; - - trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; - trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; - trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; - trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; + priv->ucode_owner = IWL_OWNERSHIP_DRIVER; - if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_trans_pcie_prepare_card_hw(trans)) { - IWL_WARN(trans, "Exit HW not ready\n"); + if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && + iwl_trans_prepare_card_hw(priv)) { + IWL_WARN(priv, "Exit HW not ready\n"); return -EIO; } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); else - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); - if (iwl_is_rfkill(trans->shrd)) { - iwl_set_hw_rfkill_state(priv(trans), true); - iwl_enable_interrupts(trans); + if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + iwl_enable_interrupts(priv); return -ERFKILL; } - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - ret = iwl_nic_init(trans); + ret = iwl_nic_init(priv); if (ret) { - IWL_ERR(trans, "Unable to init nic\n"); + IWL_ERR(priv, "Unable to init nic\n"); return ret; } /* make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(trans); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); /* really make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); return 0; } /* * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->shrd->lock and mac access + * must be called under priv->lock and mac access */ -static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) +static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) { - iwl_write_prph(bus(trans), SCD_TXFACT, mask); + iwl_write_prph(priv, SCD_TXFACT, mask); } -static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, +}; + +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, +}; +static void iwl_trans_tx_start(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rxon_context *ctx; u32 a; unsigned long flags; int i, chan; u32 reg_val; - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - trans_pcie->scd_base_addr = - iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); - a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; /* reset conext data memory */ - for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(priv, a, 0); /* reset tx status memory */ - for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); - for (; a < trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); - a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + iwl_write_targ_mem(priv, a, 0); - iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, - trans_pcie->scd_bc_tbls.dma >> 10); + iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, + priv->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ - reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, + reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, - SCD_QUEUECHAIN_SEL_ALL(trans)); - iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); + iwl_write_prph(priv, SCD_QUEUECHAIN_SEL, + SCD_QUEUECHAIN_SEL_ALL(priv)); + iwl_write_prph(priv, SCD_AGGR_SEL, 0); /* initiate the queues */ - for (i = 0; i < hw_params(trans).max_txq_num; i++) { - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + for (i = 0; i < priv->hw_params.max_txq_num; i++) { + iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << @@ -889,121 +826,108 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); } - iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, - IWL_MASK(0, hw_params(trans).max_txq_num)); + iwl_write_prph(priv, SCD_INTERRUPT_MASK, + IWL_MASK(0, priv->hw_params.max_txq_num)); /* Activate all Tx DMA/FIFO channels */ - iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); + iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); /* map queues to FIFOs */ - if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); + iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0); /* make sure all queue are not stopped */ - memset(&trans_pcie->queue_stopped[0], 0, - sizeof(trans_pcie->queue_stopped)); + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); for (i = 0; i < 4; i++) - atomic_set(&trans_pcie->queue_stop_count[i], 0); + atomic_set(&priv->queue_stop_count[i], 0); + for_each_context(priv, ctx) + ctx->last_tx_rejected = false; /* reset to 0 to enable all the queue first */ - trans_pcie->txq_ctx_active_msk = 0; + priv->txq_ctx_active_msk = 0; - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != IWLAGN_FIRST_AMPDU_QUEUE); - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != IWLAGN_FIRST_AMPDU_QUEUE); for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { int fifo = queue_to_fifo[i].fifo; int ac = queue_to_fifo[i].ac; - iwl_txq_ctx_activate(trans_pcie, i); + iwl_txq_ctx_activate(priv, i); if (fifo == IWL_TX_FIFO_UNUSED) continue; if (ac != IWL_AC_UNSET) - iwl_set_swq_id(&trans_pcie->txq[i], ac, i); - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], - fifo, 0); + iwl_set_swq_id(&priv->txq[i], ac, i); + iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* Enable L1-Active */ - iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, + iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ -static int iwl_trans_tx_stop(struct iwl_trans *trans) +static int iwl_trans_tx_stop(struct iwl_priv *priv) { int ch, txq_id; unsigned long flags; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - iwl_trans_txq_set_sched(trans, 0); + iwl_trans_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(bus(trans), - FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) - IWL_ERR(trans, "Failing on timeout while stopping" + IWL_ERR(priv, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, - iwl_read_direct32(bus(trans), - FH_TSSR_TX_STATUS_REG)); + iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - if (!trans_pcie->txq) { - IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); + if (!priv->txq) { + IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); return 0; } /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) - iwl_tx_queue_unmap(trans, txq_id); + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + iwl_tx_queue_unmap(priv, txq_id); return 0; } -static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) +static void iwl_trans_stop_device(struct iwl_priv *priv) { unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(bus(trans)->irq); - tasklet_kill(&trans_pcie->irq_tasklet); -} - -static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) -{ /* stop and reset the on-board processor */ - iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - iwl_trans_pcie_disable_sync_irq(trans); + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + trans_sync_irq(&priv->trans); /* device going down, Stop using ICT table */ - iwl_disable_ict(trans); + iwl_disable_ict(priv); /* * If a HW restart happens during firmware loading, @@ -1012,100 +936,67 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) * restart. So don't process again if the device is * already dead. */ - if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { - iwl_trans_tx_stop(trans); - iwl_trans_rx_stop(trans); + if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + iwl_trans_tx_stop(priv); + iwl_trans_rx_stop(priv); /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(bus(trans), CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv(trans)); + iwl_apm_stop(priv); } -static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) +static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, + int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd; + + if (unlikely(iwl_queue_space(q) < q->high_mark)) + return NULL; + + /* + * Set up the Tx-command (not MAC!) header. + * Store the chosen Tx queue and TFD index within the sequence field; + * after Tx, uCode's Tx response will return this value so driver can + * locate the frame within the tx queue and do post-tx processing. + */ + dev_cmd = txq->cmd[q->write_ptr]; + memset(dev_cmd, 0, sizeof(*dev_cmd)); + dev_cmd->hdr.cmd = REPLY_TX; + dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); + return &dev_cmd->cmd.tx; +} + +static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) +{ + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr]; struct iwl_cmd_meta *out_meta; - struct iwl_tx_queue *txq; - struct iwl_queue *q; dma_addr_t phys_addr = 0; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; u16 len, firstlen, secondlen; - u16 seq_number = 0; u8 wait_write_ptr = 0; - u8 txq_id; - u8 tid = 0; - bool is_agg = false; - __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); - /* - * Send this frame after DTIM -- there's a special queue - * reserved for this for contexts that support AP mode. - */ - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - txq_id = trans_pcie->mcast_queue[ctx]; - - /* - * The microcode will clear the more data - * bit in the last frame it transmits. - */ - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) - txq_id = IWL_AUX_QUEUE; - else - txq_id = - trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; - - if (ieee80211_is_data_qos(fc)) { - u8 *qc = NULL; - struct iwl_tid_data *tid_data; - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - tid_data = &trans->shrd->tid_data[sta_id][tid]; - - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) - return -1; - - seq_number = tid_data->seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); - seq_number += 0x10; - /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - tid_data->agg.state == IWL_AGG_ON) { - txq_id = tid_data->agg.txq_id; - is_agg = true; - } - } - - txq = &trans_pcie->txq[txq_id]; - q = &txq->q; - /* Set up driver data for this TFD */ - txq->skbs[q->write_ptr] = skb; - txq->cmd[q->write_ptr] = dev_cmd; - - dev_cmd->hdr.cmd = REPLY_TX; - dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); + memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); + txq->txb[q->write_ptr].skb = skb; + txq->txb[q->write_ptr].ctx = ctx; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_meta = &txq->meta[q->write_ptr]; @@ -1129,10 +1020,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = dma_map_single(bus(trans)->dev, + txcmd_phys = dma_map_single(priv->bus->dev, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) + if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) return -1; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1148,10 +1039,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * if any (802.11 null frames have no payload). */ secondlen = skb->len - hdr_len; if (secondlen > 0) { - phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, + phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { - dma_unmap_single(bus(trans)->dev, + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { + dma_unmap_single(priv->bus->dev, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); @@ -1160,35 +1051,35 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, } /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); if (secondlen > 0) - iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", + IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", le16_to_cpu(dev_cmd->hdr.sequence)); - IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); /* Set up entry for this TFD in Tx byte-count array */ - if (is_agg) - iwl_trans_txq_update_byte_cnt_tbl(trans, txq, + if (ampdu) + iwl_trans_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len)); - dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); - trace_iwlwifi_dev_tx(priv(trans), + trace_iwlwifi_dev_tx(priv, &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], sizeof(struct iwl_tfd), &dev_cmd->hdr, firstlen, @@ -1196,14 +1087,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(trans, txq); - - if (ieee80211_is_data_qos(fc)) { - trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; - if (!ieee80211_has_morefrags(fc)) - trans->shrd->tid_data[sta_id][tid].seq_number = - seq_number; - } + iwl_txq_update_write_ptr(priv, txq); /* * At this point the frame is "transmitted" successfully @@ -1211,777 +1095,82 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * regardless of the value of ret. "ret" only indicates * whether or not we should update the write pointer. */ - if (iwl_queue_space(q) < q->high_mark) { + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { txq->need_update = 1; - iwl_txq_update_write_ptr(trans, txq); + iwl_txq_update_write_ptr(priv, txq); } else { - iwl_stop_queue(trans, txq); + iwl_stop_queue(priv, txq); } } return 0; } -static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) +static void iwl_trans_kick_nic(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ - iwl_write32(bus(trans), CSR_RESET, 0); -} - -static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - int err; - - trans_pcie->inta_mask = CSR_INI_SET_MASK; - - tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)trans); - - iwl_alloc_isr_ict(trans); - - err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, trans); - if (err) { - IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); - iwl_free_isr_ict(trans); - return err; - } - - INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); - return 0; -} - -static int iwlagn_txq_check_empty(struct iwl_trans *trans, - int sta_id, u8 tid, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_queue *q = &trans_pcie->txq[txq_id].q; - struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; - - lockdep_assert_held(&trans->shrd->sta_lock); - - switch (trans->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_DELBA: - /* We are reclaiming the last packet of the */ - /* aggregated HW queue */ - if ((txq_id == tid_data->agg.txq_id) && - (q->read_ptr == q->write_ptr)) { - IWL_DEBUG_HT(trans, - "HW queue empty: continue DELBA flow\n"); - iwl_trans_pcie_txq_agg_disable(trans, txq_id); - tid_data->agg.state = IWL_AGG_OFF; - iwl_stop_tx_ba_trans_ready(priv(trans), - NUM_IWL_RXON_CTX, - sta_id, tid); - iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); - } - break; - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* We are reclaiming the last packet of the queue */ - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(trans, - "HW queue empty: continue ADDBA flow\n"); - tid_data->agg.state = IWL_AGG_ON; - iwl_start_tx_ba_trans_ready(priv(trans), - NUM_IWL_RXON_CTX, - sta_id, tid); - } - break; - } - - return 0; -} - -static void iwl_free_tfds_in_queue(struct iwl_trans *trans, - int sta_id, int tid, int freed) -{ - lockdep_assert_held(&trans->shrd->sta_lock); - - if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) - trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n", - trans->shrd->tid_data[sta_id][tid].tfds_in_queue, - freed); - trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; - } -} - -static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - /* n_bd is usually 256 => n_bd - 1 = 0xff */ - int tfd_num = ssn & (txq->q.n_bd - 1); - int freed = 0; - u8 agg_state; - bool cond; - - txq->time_stamp = jiffies; - - if (txq->sched_retry) { - agg_state = - trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; - cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); - } else { - cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); - } - - if (txq->q.read_ptr != tfd_num) { - IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " - "scd_ssn=%d idx=%d txq=%d swq=%d\n", - ssn , tfd_num, txq_id, txq->swq_id); - freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); - if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) - iwl_wake_queue(trans, txq); - } - - iwl_free_tfds_in_queue(trans, sta_id, tid, freed); - iwlagn_txq_check_empty(trans, sta_id, tid, txq_id); -} - -static void iwl_trans_pcie_free(struct iwl_trans *trans) -{ - iwl_trans_pcie_tx_free(trans); - iwl_trans_pcie_rx_free(trans); - free_irq(bus(trans)->irq, trans); - iwl_free_isr_ict(trans); - trans->shrd->trans = NULL; - kfree(trans); -} - -#ifdef CONFIG_PM - -static int iwl_trans_pcie_suspend(struct iwl_trans *trans) -{ - /* - * This function is called when system goes into suspend state - * mac80211 will call iwl_mac_stop() from the mac80211 suspend function - * first but since iwl_mac_stop() has no knowledge of who the caller is, - * it will not call apm_ops.stop() to stop the DMA operation. - * Calling apm_ops.stop here to make sure we stop the DMA. - * - * But of course ... if we have configured WoWLAN then we did other - * things already :-) - */ - if (!trans->shrd->wowlan) - iwl_apm_stop(priv(trans)); - - return 0; -} - -static int iwl_trans_pcie_resume(struct iwl_trans *trans) -{ - bool hw_rfkill = false; - - iwl_enable_interrupts(trans); - - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rfkill = true; - - if (hw_rfkill) - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - else - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - - iwl_set_hw_rfkill_state(priv(trans), hw_rfkill); - - return 0; + iwl_write32(priv, CSR_RESET, 0); } -#else /* CONFIG_PM */ -static int iwl_trans_pcie_suspend(struct iwl_trans *trans) -{ return 0; } - -static int iwl_trans_pcie_resume(struct iwl_trans *trans) -{ return 0; } -#endif /* CONFIG_PM */ - -static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, - u8 ctx) +static void iwl_trans_sync_irq(struct iwl_priv *priv) { - u8 ac, txq_id; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - for (ac = 0; ac < AC_NUM; ac++) { - txq_id = trans_pcie->ac_to_queue[ctx][ac]; - IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", - ac, - (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) - ? "stopped" : "awake"); - iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); - } -} - -const struct iwl_trans_ops trans_ops_pcie; - -static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) -{ - struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + - sizeof(struct iwl_trans_pcie), - GFP_KERNEL); - if (iwl_trans) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(iwl_trans); - iwl_trans->ops = &trans_ops_pcie; - iwl_trans->shrd = shrd; - trans_pcie->trans = iwl_trans; - spin_lock_init(&iwl_trans->hcmd_lock); - } - - return iwl_trans; -} - -static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - iwl_stop_queue(trans, &trans_pcie->txq[txq_id]); -} - -#define IWL_FLUSH_WAIT_MS 2000 - -static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - int cnt; - unsigned long now = jiffies; - int ret = 0; - - /* waiting for all the tx frames complete might take a while */ - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - if (cnt == trans->shrd->cmd_queue) - continue; - txq = &trans_pcie->txq[cnt]; - q = &txq->q; - while (q->read_ptr != q->write_ptr && !time_after(jiffies, - now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) - msleep(1); - - if (q->read_ptr != q->write_ptr) { - IWL_ERR(trans, "fail to flush all tx fifo queues\n"); - ret = -ETIMEDOUT; - break; - } - } - return ret; -} - -/* - * On every watchdog tick we check (latest) time stamp. If it does not - * change during timeout period and queue is not empty we reset firmware. - */ -static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; - struct iwl_queue *q = &txq->q; - unsigned long timeout; - - if (q->read_ptr == q->write_ptr) { - txq->time_stamp = jiffies; - return 0; - } - - timeout = txq->time_stamp + - msecs_to_jiffies(hw_params(trans).wd_timeout); - - if (time_after(jiffies, timeout)) { - IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, - hw_params(trans).wd_timeout); - IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n", - q->read_ptr, q->write_ptr); - return 1; - } - - return 0; + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus->irq); + tasklet_kill(&priv->irq_tasklet); } -static const char *get_fh_string(int cmd) +static void iwl_trans_free(struct iwl_priv *priv) { - switch (cmd) { - IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); - IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); - IWL_CMD(FH_RSCSR_CHNL0_WPTR); - IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); - IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); - IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); - IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - } + free_irq(priv->bus->irq, priv); + iwl_free_isr_ict(priv); } -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) -{ - int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif - static const u32 fh_tbl[] = { - FH_RSCSR_CHNL0_STTS_WPTR_REG, - FH_RSCSR_CHNL0_RBDCB_BASE_REG, - FH_RSCSR_CHNL0_WPTR, - FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_MEM_RSSR_SHARED_CTRL_REG, - FH_MEM_RSSR_RX_STATUS_REG, - FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG - }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - pos += scnprintf(*buf + pos, bufsz - pos, - "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - pos += scnprintf(*buf + pos, bufsz - pos, - " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); - } - return pos; - } -#endif - IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - IWL_ERR(trans, " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); - } - return 0; -} +static const struct iwl_trans_ops trans_ops = { + .start_device = iwl_trans_start_device, + .prepare_card_hw = iwl_trans_prepare_card_hw, + .stop_device = iwl_trans_stop_device, -static const char *get_csr_string(int cmd) -{ - switch (cmd) { - IWL_CMD(CSR_HW_IF_CONFIG_REG); - IWL_CMD(CSR_INT_COALESCING); - IWL_CMD(CSR_INT); - IWL_CMD(CSR_INT_MASK); - IWL_CMD(CSR_FH_INT_STATUS); - IWL_CMD(CSR_GPIO_IN); - IWL_CMD(CSR_RESET); - IWL_CMD(CSR_GP_CNTRL); - IWL_CMD(CSR_HW_REV); - IWL_CMD(CSR_EEPROM_REG); - IWL_CMD(CSR_EEPROM_GP); - IWL_CMD(CSR_OTP_GP_REG); - IWL_CMD(CSR_GIO_REG); - IWL_CMD(CSR_GP_UCODE_REG); - IWL_CMD(CSR_GP_DRIVER_REG); - IWL_CMD(CSR_UCODE_DRV_GP1); - IWL_CMD(CSR_UCODE_DRV_GP2); - IWL_CMD(CSR_LED_REG); - IWL_CMD(CSR_DRAM_INT_TBL_REG); - IWL_CMD(CSR_GIO_CHICKEN_BITS); - IWL_CMD(CSR_ANA_PLL_CFG); - IWL_CMD(CSR_HW_REV_WA_REG); - IWL_CMD(CSR_DBG_HPET_MEM_REG); - default: - return "UNKNOWN"; - } -} + .tx_start = iwl_trans_tx_start, -void iwl_dump_csr(struct iwl_trans *trans) -{ - int i; - static const u32 csr_tbl[] = { - CSR_HW_IF_CONFIG_REG, - CSR_INT_COALESCING, - CSR_INT, - CSR_INT_MASK, - CSR_FH_INT_STATUS, - CSR_GPIO_IN, - CSR_RESET, - CSR_GP_CNTRL, - CSR_HW_REV, - CSR_EEPROM_REG, - CSR_EEPROM_GP, - CSR_OTP_GP_REG, - CSR_GIO_REG, - CSR_GP_UCODE_REG, - CSR_GP_DRIVER_REG, - CSR_UCODE_DRV_GP1, - CSR_UCODE_DRV_GP2, - CSR_LED_REG, - CSR_DRAM_INT_TBL_REG, - CSR_GIO_CHICKEN_BITS, - CSR_ANA_PLL_CFG, - CSR_HW_REV_WA_REG, - CSR_DBG_HPET_MEM_REG - }; - IWL_ERR(trans, "CSR values:\n"); - IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is " - "CSR_INT_PERIODIC_REG)\n"); - for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { - IWL_ERR(trans, " %25s: 0X%08x\n", - get_csr_string(csr_tbl[i]), - iwl_read32(bus(trans), csr_tbl[i])); - } -} + .rx_free = iwl_trans_rx_free, + .tx_free = iwl_trans_tx_free, -#ifdef CONFIG_IWLWIFI_DEBUGFS -/* create and remove of files */ -#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, trans, \ - &iwl_dbgfs_##name##_ops)) \ - return -ENOMEM; \ -} while (0) + .send_cmd = iwl_send_cmd, + .send_cmd_pdu = iwl_send_cmd_pdu, -/* file operation */ -#define DEBUGFS_READ_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ - char __user *user_buf, \ - size_t count, loff_t *ppos); + .get_tx_cmd = iwl_trans_get_tx_cmd, + .tx = iwl_trans_tx, -#define DEBUGFS_WRITE_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ - const char __user *user_buf, \ - size_t count, loff_t *ppos); + .txq_agg_disable = iwl_trans_txq_agg_disable, + .txq_agg_setup = iwl_trans_txq_agg_setup, + .kick_nic = iwl_trans_kick_nic, -static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -#define DEBUGFS_READ_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_WRITE_FILE_OPS(name) \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ + .sync_irq = iwl_trans_sync_irq, + .free = iwl_trans_free, }; -#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - char *buf; - int pos = 0; - int cnt; - int ret; - const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; - - if (!trans_pcie->txq) { - IWL_ERR(trans, "txq not ready\n"); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - txq = &trans_pcie->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "hwq %.2d: read=%u write=%u stop=%d" - " swq_id=%#.2x (ac %d/hwq %d)\n", - cnt, q->read_ptr, q->write_ptr, - !!test_bit(cnt, trans_pcie->queue_stopped), - txq->swq_id, txq->swq_id & 3, - (txq->swq_id >> 2) & 0x1f); - if (cnt >= 4) - continue; - /* for the ACs, display the stop count too */ - pos += scnprintf(buf + pos, bufsz - pos, - " stop-count: %d\n", - atomic_read(&trans_pcie->queue_stop_count[cnt])); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - if (rxq->rb_stts) { - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - } else { - pos += scnprintf(buf + pos, bufsz - pos, - "closed_rb_num: Not Allocated\n"); - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_log_event_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -ENOMEM; - - ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - } - return ret; -} - -static ssize_t iwl_dbgfs_log_event_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - u32 event_log_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &event_log_flag) != 1) - return -EFAULT; - if (event_log_flag == 1) - iwl_dump_nic_event_log(trans, true, NULL, false); - - return count; -} - -static ssize_t iwl_dbgfs_interrupt_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - int pos = 0; - char *buf; - int bufsz = 24 * 64; /* 24 items * 64 char per item */ - ssize_t ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(trans, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, - "Interrupt Statistics Report:\n"); - - pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", - isr_stats->hw); - pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", - isr_stats->sw); - if (isr_stats->sw || isr_stats->hw) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tLast Restarting Code: 0x%X\n", - isr_stats->err_code); - } -#ifdef CONFIG_IWLWIFI_DEBUG - pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", - isr_stats->sch); - pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", - isr_stats->alive); -#endif - pos += scnprintf(buf + pos, bufsz - pos, - "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill); - - pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", - isr_stats->ctkill); - - pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", - isr_stats->wakeup); - - pos += scnprintf(buf + pos, bufsz - pos, - "Rx command responses:\t\t %u\n", isr_stats->rx); - - pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", - isr_stats->tx); - - pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", - isr_stats->unhandled); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_interrupt_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) { - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - char buf[8]; - int buf_size; - u32 reset_flag; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &reset_flag) != 1) - return -EFAULT; - if (reset_flag == 0) - memset(isr_stats, 0, sizeof(*isr_stats)); - - return count; -} + int err; -static ssize_t iwl_dbgfs_csr_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char buf[8]; - int buf_size; - int csr; + priv->trans.ops = &trans_ops; + priv->trans.priv = priv; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &csr) != 1) - return -EFAULT; + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); - iwl_dump_csr(trans); + iwl_alloc_isr_ict(priv); - return count; -} - -static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -EFAULT; - - ret = pos = iwl_dump_fh(trans, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, - count, ppos, buf, pos); - kfree(buf); + err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); + iwl_free_isr_ict(priv); + return err; } - return ret; -} + INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); -DEBUGFS_READ_WRITE_FILE_OPS(log_event); -DEBUGFS_READ_WRITE_FILE_OPS(interrupt); -DEBUGFS_READ_FILE_OPS(fh_reg); -DEBUGFS_READ_FILE_OPS(rx_queue); -DEBUGFS_READ_FILE_OPS(tx_queue); -DEBUGFS_WRITE_FILE_OPS(csr); - -/* - * Create the debugfs files and directories - * - */ -static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ - DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); - DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); - DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); - DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); return 0; } -#else -static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ return 0; } - -#endif /*CONFIG_IWLWIFI_DEBUGFS */ - -const struct iwl_trans_ops trans_ops_pcie = { - .alloc = iwl_trans_pcie_alloc, - .request_irq = iwl_trans_pcie_request_irq, - .start_device = iwl_trans_pcie_start_device, - .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, - .stop_device = iwl_trans_pcie_stop_device, - - .tx_start = iwl_trans_pcie_tx_start, - .wake_any_queue = iwl_trans_pcie_wake_any_queue, - - .send_cmd = iwl_trans_pcie_send_cmd, - .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, - - .tx = iwl_trans_pcie_tx, - .reclaim = iwl_trans_pcie_reclaim, - - .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, - .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, - .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, - - .kick_nic = iwl_trans_pcie_kick_nic, - - .free = iwl_trans_pcie_free, - .stop_queue = iwl_trans_pcie_stop_queue, - - .dbgfs_register = iwl_trans_pcie_dbgfs_register, - - .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, - .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, - - .suspend = iwl_trans_pcie_suspend, - .resume = iwl_trans_pcie_resume, -}; - diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index 71a6fb05356a..7993aa7ae668 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -63,295 +63,163 @@ #ifndef __iwl_trans_h__ #define __iwl_trans_h__ -#include -#include - -#include "iwl-shared.h" -#include "iwl-commands.h" - /*This file includes the declaration that are exported from the transport * layer */ struct iwl_priv; -struct iwl_shared; - -#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) -#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) - -enum { - CMD_SYNC = 0, - CMD_ASYNC = BIT(0), - CMD_WANT_SKB = BIT(1), - CMD_ON_DEMAND = BIT(2), -}; - -#define DEF_CMD_PAYLOAD_SIZE 320 - -/** - * struct iwl_device_cmd - * - * For allocation of the command and tx queues, this establishes the overall - * size of the largest command we send to uCode, except for commands that - * aren't fully copied and use other TFD space. - */ -struct iwl_device_cmd { - struct iwl_cmd_header hdr; /* uCode API */ - union { - u32 flags; - u8 val8; - u16 val16; - u32 val32; - struct iwl_tx_cmd tx; - struct iwl6000_channel_switch_cmd chswitch; - u8 payload[DEF_CMD_PAYLOAD_SIZE]; - } __packed cmd; -} __packed; - -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) - -#define IWL_MAX_CMD_TFDS 2 - -enum iwl_hcmd_dataflag { - IWL_HCMD_DFL_NOCOPY = BIT(0), -}; - -/** - * struct iwl_host_cmd - Host command to the uCode - * @data: array of chunks that composes the data of the host command - * @reply_page: pointer to the page that holds the response to the host command - * @callback: - * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC - * @len: array of the lenths of the chunks in data - * @dataflags: - * @id: id of the host command - */ -struct iwl_host_cmd { - const void *data[IWL_MAX_CMD_TFDS]; - unsigned long reply_page; - void (*callback)(struct iwl_shared *shrd, - struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt); - u32 flags; - u16 len[IWL_MAX_CMD_TFDS]; - u8 dataflags[IWL_MAX_CMD_TFDS]; - u8 id; -}; +struct iwl_rxon_context; +struct iwl_host_cmd; /** * struct iwl_trans_ops - transport specific operations - * @alloc: allocates the meta data (not the queues themselves) - * @request_irq: requests IRQ - will be called before the FW load in probe flow * @start_device: allocates and inits all the resources for the transport * layer. * @prepare_card_hw: claim the ownership on the HW. Will be called during * probe. * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. - * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) + * @rx_free: frees the rx memory + * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb - * @reclaim: free packet until ssn. Returns a list of freed packets. - * @tx_agg_alloc: allocate resources for a TX BA session - * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. - * @tx_agg_disable: de-configure a Tx queue to send AMPDUs + * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... - * @stop_queue: stop a specific queue - * @check_stuck_queue: check if a specific queue is stuck - * @wait_tx_queue_empty: wait until all tx queues are empty - * @dbgfs_register: add the dbgfs files under this directory. Files will be - * automatically deleted. - * @suspend: stop the device unless WoWLAN is configured - * @resume: resume activity of the device */ struct iwl_trans_ops { - struct iwl_trans *(*alloc)(struct iwl_shared *shrd); - int (*request_irq)(struct iwl_trans *iwl_trans); - int (*start_device)(struct iwl_trans *trans); - int (*prepare_card_hw)(struct iwl_trans *trans); - void (*stop_device)(struct iwl_trans *trans); - void (*tx_start)(struct iwl_trans *trans); - - void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx); + int (*start_device)(struct iwl_priv *priv); + int (*prepare_card_hw)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); + void (*tx_start)(struct iwl_priv *priv); + void (*tx_free)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_priv *priv); - int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, + int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, const void *data); - int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); - void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs); - - int (*tx_agg_disable)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid); - int (*tx_agg_alloc)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, int tid, - u16 *ssn); - void (*tx_agg_setup)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, int tid, - int frame_limit); - - void (*kick_nic)(struct iwl_trans *trans); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx); - void (*free)(struct iwl_trans *trans); + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); + void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); - void (*stop_queue)(struct iwl_trans *trans, int q); + void (*kick_nic)(struct iwl_priv *priv); - int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); - int (*check_stuck_queue)(struct iwl_trans *trans, int q); - int (*wait_tx_queue_empty)(struct iwl_trans *trans); - - int (*suspend)(struct iwl_trans *trans); - int (*resume)(struct iwl_trans *trans); + void (*sync_irq)(struct iwl_priv *priv); + void (*free)(struct iwl_priv *priv); }; -/** - * struct iwl_trans - transport common data - * @ops - pointer to iwl_trans_ops - * @shrd - pointer to iwl_shared which holds shared data from the upper layer - * @hcmd_lock: protects HCMD - */ struct iwl_trans { const struct iwl_trans_ops *ops; - struct iwl_shared *shrd; - spinlock_t hcmd_lock; - - /* pointer to trans specific struct */ - /*Ensure that this pointer will always be aligned to sizeof pointer */ - char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); + struct iwl_priv *priv; }; -static inline int iwl_trans_request_irq(struct iwl_trans *trans) +static inline int trans_start_device(struct iwl_trans *trans) { - return trans->ops->request_irq(trans); + return trans->ops->start_device(trans->priv); } -static inline int iwl_trans_start_device(struct iwl_trans *trans) +static inline int trans_prepare_card_hw(struct iwl_trans *trans) { - return trans->ops->start_device(trans); + return trans->ops->prepare_card_hw(trans->priv); } -static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) +static inline void trans_stop_device(struct iwl_trans *trans) { - return trans->ops->prepare_card_hw(trans); + trans->ops->stop_device(trans->priv); } -static inline void iwl_trans_stop_device(struct iwl_trans *trans) +static inline void trans_tx_start(struct iwl_trans *trans) { - trans->ops->stop_device(trans); + trans->ops->tx_start(trans->priv); } -static inline void iwl_trans_tx_start(struct iwl_trans *trans) +static inline void trans_rx_free(struct iwl_trans *trans) { - trans->ops->tx_start(trans); + trans->ops->rx_free(trans->priv); } -static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx) +static inline void trans_tx_free(struct iwl_trans *trans) { - trans->ops->wake_any_queue(trans, ctx); + trans->ops->tx_free(trans->priv); } - -static inline int iwl_trans_send_cmd(struct iwl_trans *trans, +static inline int trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return trans->ops->send_cmd(trans, cmd); + return trans->ops->send_cmd(trans->priv, cmd); } -static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data) +static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, + u16 len, const void *data) { - return trans->ops->send_cmd_pdu(trans, id, flags, len, data); + return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); } -static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) +static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, + int txq_id) { - return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); + return trans->ops->get_tx_cmd(trans->priv, txq_id); } -static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, - int tid, int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs) +static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) { - trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs); + return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } -static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid) +static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { - return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid); + return trans->ops->txq_agg_disable(trans->priv, txq_id, + ssn_idx, tx_fifo); } -static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, u16 *ssn) +static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, + int tid, int frame_limit) { - return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn); + trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); } - -static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, - int frame_limit) +static inline void trans_kick_nic(struct iwl_trans *trans) { - trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit); + trans->ops->kick_nic(trans->priv); } -static inline void iwl_trans_kick_nic(struct iwl_trans *trans) +static inline void trans_sync_irq(struct iwl_trans *trans) { - trans->ops->kick_nic(trans); + trans->ops->sync_irq(trans->priv); } -static inline void iwl_trans_free(struct iwl_trans *trans) +static inline void trans_free(struct iwl_trans *trans) { - trans->ops->free(trans); + trans->ops->free(trans->priv); } -static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q) -{ - trans->ops->stop_queue(trans, q); -} - -static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) -{ - return trans->ops->wait_tx_queue_empty(trans); -} +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); -static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q) -{ - return trans->ops->check_stuck_queue(trans, q); -} -static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ - return trans->ops->dbgfs_register(trans, dir); -} - -static inline int iwl_trans_suspend(struct iwl_trans *trans) -{ - return trans->ops->suspend(trans); -} - -static inline int iwl_trans_resume(struct iwl_trans *trans) -{ - return trans->ops->resume(trans); -} +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too */ -/***************************************************** -* Transport layers implementations -******************************************************/ -extern const struct iwl_trans_ops trans_ops_pcie; +struct iwl_tx_queue; +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); #endif /* __iwl_trans_h__ */ diff --git a/trunk/drivers/net/wireless/libertas/README b/trunk/drivers/net/wireless/libertas/README index 91f2ca90c70f..1453eec82a99 100644 --- a/trunk/drivers/net/wireless/libertas/README +++ b/trunk/drivers/net/wireless/libertas/README @@ -238,3 +238,28 @@ hostsleep echo "1" > hostsleep : enable host sleep. echo "0" > hostsleep : disable host sleep +======================== +IWCONFIG COMMANDS +======================== +power period + + This command is used to configure the station in deep sleep mode / + auto deep sleep mode. + + The timer is implemented to monitor the activities (command, event, + etc.). When an activity is detected station will exit from deep + sleep mode automatically and restart the timer. At timer expiry + (no activity for defined time period) the deep sleep mode is entered + automatically. + + Note: this command is for SDIO interface only. + + Usage: + To enable deep sleep mode do: + iwconfig wlan0 power period 0 + To enable auto deep sleep mode with idle time period 5 seconds do: + iwconfig wlan0 power period 5 + To disable deep sleep/auto deep sleep mode do: + iwconfig wlan0 power period -1 + +============================================================================== diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h index b9ff0dc53e8d..814838916b82 100644 --- a/trunk/drivers/net/wireless/libertas/dev.h +++ b/trunk/drivers/net/wireless/libertas/dev.h @@ -190,8 +190,8 @@ static inline int lbs_iface_active(struct lbs_private *priv) int r; r = netif_running(priv->dev); - if (priv->mesh_dev) - r |= netif_running(priv->mesh_dev); + if (priv->mesh_dev); + r |= netif_running(priv->dev); return r; } diff --git a/trunk/drivers/net/wireless/libertas/if_usb.c b/trunk/drivers/net/wireless/libertas/if_usb.c index 8147f1e2a0b0..0c846f5a646a 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.c +++ b/trunk/drivers/net/wireless/libertas/if_usb.c @@ -973,23 +973,6 @@ static const struct { { MODEL_8682, "libertas/usb8682.bin" } }; -#ifdef CONFIG_OLPC - -static int try_olpc_fw(struct if_usb_card *cardp) -{ - int retval = -ENOENT; - - /* try the OLPC firmware first; fall back to fw_table list */ - if (machine_is_olpc() && cardp->model == MODEL_8388) - retval = request_firmware(&cardp->fw, - "libertas/usb8388_olpc.bin", &cardp->udev->dev); - return retval; -} - -#else -static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; } -#endif /* !CONFIG_OLPC */ - static int get_fw(struct if_usb_card *cardp, const char *fwname) { int i; @@ -998,10 +981,6 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname) if (fwname) return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); - /* Handle OLPC firmware */ - if (try_olpc_fw(cardp) == 0) - return 0; - /* Otherwise search for firmware to use */ for (i = 0; i < ARRAY_SIZE(fw_table); i++) { if (fw_table[i].model != cardp->model) diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 6fd53e4e3fe6..c979a909303e 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -792,6 +792,139 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) return 0; } +/* + * This function informs the CFG802.11 subsystem of a new BSS connection. + * + * The following information are sent to the CFG802.11 subsystem + * to register the new BSS connection. If we do not register the new BSS, + * a kernel panic will result. + * - MAC address + * - Capabilities + * - Beacon period + * - RSSI value + * - Channel + * - Supported rates IE + * - Extended capabilities IE + * - DS parameter set IE + * - HT Capability IE + * - Vendor Specific IE (221) + * - WPA IE + * - RSN IE + */ +static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid) +{ + struct mwifiex_bssdescriptor *scan_table; + int i, j; + struct ieee80211_channel *chan; + u8 *ie, *ie_buf; + u32 ie_len; + u8 *beacon; + int beacon_size; + u8 element_id, element_len; + +#define MAX_IE_BUF 2048 + ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); + if (!ie_buf) { + dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n", + __func__); + return -ENOMEM; + } + + scan_table = priv->adapter->scan_table; + for (i = 0; i < priv->adapter->num_in_scan_table; i++) { + if (ssid) { + /* Inform specific BSS only */ + if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, + ssid->ssid_len)) + continue; + } + memset(ie_buf, 0, MAX_IE_BUF); + ie_buf[0] = WLAN_EID_SSID; + ie_buf[1] = scan_table[i].ssid.ssid_len; + memcpy(&ie_buf[sizeof(struct ieee_types_header)], + scan_table[i].ssid.ssid, ie_buf[1]); + + ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header); + ie_len = ie_buf[1] + sizeof(struct ieee_types_header); + + ie[0] = WLAN_EID_SUPP_RATES; + + for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) { + if (!scan_table[i].supported_rates[j]) + break; + else + ie[j + sizeof(struct ieee_types_header)] = + scan_table[i].supported_rates[j]; + } + + ie[1] = j; + ie_len += ie[1] + sizeof(struct ieee_types_header); + + beacon = scan_table[i].beacon_buf; + beacon_size = scan_table[i].beacon_buf_size; + + /* Skip time stamp, beacon interval and capability */ + + if (beacon) { + beacon += sizeof(scan_table[i].beacon_period) + + sizeof(scan_table[i].time_stamp) + + +sizeof(scan_table[i].cap_info_bitmap); + + beacon_size -= sizeof(scan_table[i].beacon_period) + + sizeof(scan_table[i].time_stamp) + + sizeof(scan_table[i].cap_info_bitmap); + } + + while (beacon_size >= sizeof(struct ieee_types_header)) { + ie = ie_buf + ie_len; + element_id = *beacon; + element_len = *(beacon + 1); + if (beacon_size < (int) element_len + + sizeof(struct ieee_types_header)) { + dev_err(priv->adapter->dev, "%s: in processing" + " IE, bytes left < IE length\n", + __func__); + break; + } + switch (element_id) { + case WLAN_EID_EXT_CAPABILITY: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_VENDOR_SPECIFIC: + case WLAN_EID_RSN: + case WLAN_EID_BSS_AC_ACCESS_DELAY: + ie[0] = element_id; + ie[1] = element_len; + memcpy(&ie[sizeof(struct ieee_types_header)], + (u8 *) beacon + + sizeof(struct ieee_types_header), + element_len); + ie_len += ie[1] + + sizeof(struct ieee_types_header); + break; + default: + break; + } + beacon += element_len + + sizeof(struct ieee_types_header); + beacon_size -= element_len + + sizeof(struct ieee_types_header); + } + chan = ieee80211_get_channel(priv->wdev->wiphy, + scan_table[i].freq); + cfg80211_inform_bss(priv->wdev->wiphy, chan, + scan_table[i].mac_address, + 0, scan_table[i].cap_info_bitmap, + scan_table[i].beacon_period, + ie_buf, ie_len, + scan_table[i].rssi, GFP_KERNEL); + } + + kfree(ie_buf); + return 0; +} + /* * This function connects with a BSS. * @@ -804,7 +937,8 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) * For Infra mode, the function returns failure if the specified SSID * is not found in scan table. However, for Ad-Hoc mode, it can create * the IBSS if it does not exist. On successful completion in either case, - * the function notifies the CFG802.11 subsystem of the new BSS connection. + * the function notifies the CFG802.11 subsystem of the new BSS connection, + * otherwise the kernel will panic. */ static int mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, @@ -812,11 +946,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, struct cfg80211_connect_params *sme, bool privacy) { struct mwifiex_802_11_ssid req_ssid; + struct mwifiex_ssid_bssid ssid_bssid; int ret, auth_type = 0; - struct cfg80211_bss *bss = NULL; - u8 is_scanning_required = 0; memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); + memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); req_ssid.ssid_len = ssid_len; if (ssid_len > IEEE80211_MAX_SSID_LEN) { @@ -894,48 +1028,30 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, return -EFAULT; } - /* - * Scan entries are valid for some time (15 sec). So we can save one - * active scan time if we just try cfg80211_get_bss first. If it fails - * then request scan and cfg80211_get_bss() again for final output. - */ - while (1) { - if (is_scanning_required) { - /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, &req_ssid)) { - dev_err(priv->adapter->dev, "scan error\n"); - return -EFAULT; - } - } - /* Find the BSS we want using available scan results */ - if (mode == NL80211_IFTYPE_ADHOC) - bss = cfg80211_get_bss(priv->wdev->wiphy, channel, - bssid, ssid, ssid_len, - WLAN_CAPABILITY_IBSS, - WLAN_CAPABILITY_IBSS); - else - bss = cfg80211_get_bss(priv->wdev->wiphy, channel, - bssid, ssid, ssid_len, - WLAN_CAPABILITY_ESS, - WLAN_CAPABILITY_ESS); - - if (!bss) { - if (is_scanning_required) { - dev_warn(priv->adapter->dev, "assoc: requested " - "bss not found in scan results\n"); - break; - } - is_scanning_required = 1; - } else { - dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", - (char *) req_ssid.ssid, bss->bssid); - memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); - break; - } + memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); + + if (mode != NL80211_IFTYPE_ADHOC) { + if (mwifiex_find_best_bss(priv, &ssid_bssid)) + return -EFAULT; + /* Inform the BSS information to kernel, otherwise + * kernel will give a panic after successful assoc */ + if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) + return -EFAULT; } - if (mwifiex_bss_start(priv, bss, &req_ssid)) + dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", + (char *) req_ssid.ssid, ssid_bssid.bssid); + + memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6); + + /* Connect to BSS by ESSID */ + memset(&ssid_bssid.bssid, 0, ETH_ALEN); + + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + + if (mwifiex_bss_start(priv, &ssid_bssid)) return -EFAULT; if (mode == NL80211_IFTYPE_ADHOC) { @@ -1300,8 +1416,13 @@ mwifiex_cfg80211_results(struct work_struct *work) MWIFIEX_SCAN_TYPE_ACTIVE; scan_req->chan_list[i].scan_time = 0; } - if (mwifiex_set_user_scan_ioctl(priv, scan_req)) + if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { ret = -EFAULT; + goto done; + } + if (mwifiex_inform_bss_from_scan_result(priv, NULL)) + ret = -EFAULT; +done: priv->scan_result_status = ret; dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", __func__); diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index f23ec72ed4fe..4fee0993b186 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -821,14 +821,6 @@ struct host_cmd_ds_txpwr_cfg { __le32 mode; } __packed; -struct mwifiex_bcn_param { - u8 bssid[ETH_ALEN]; - u8 rssi; - __le32 timestamp[2]; - __le16 beacon_period; - __le16 cap_info_bitmap; -} __packed; - #define MWIFIEX_USER_SCAN_CHAN_MAX 50 #define MWIFIEX_MAX_SSID_LIST_LENGTH 10 @@ -869,6 +861,13 @@ struct mwifiex_user_scan_ssid { } __packed; struct mwifiex_user_scan_cfg { + /* + * Flag set to keep the previous scan table intact + * + * If set, the scan results will accumulate, replacing any previous + * matched entries for a BSS with the new scan data + */ + u8 keep_previous_scan; /* * BSS mode to be sent in the firmware command */ diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c index 26e685a31bc0..a57c8de46d37 100644 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ b/trunk/drivers/net/wireless/mwifiex/init.c @@ -152,6 +152,19 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) { int ret; + u32 buf_size; + struct mwifiex_bssdescriptor *temp_scan_table; + + /* Allocate buffer to store the BSSID list */ + buf_size = sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP; + temp_scan_table = kzalloc(buf_size, GFP_KERNEL); + if (!temp_scan_table) { + dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", + __func__); + return -ENOMEM; + } + + adapter->scan_table = temp_scan_table; /* Allocate command buffer */ ret = mwifiex_alloc_cmd_buffer(adapter); @@ -209,8 +222,14 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; + adapter->num_in_scan_table = 0; + memset(adapter->scan_table, 0, + (sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP)); adapter->scan_probes = 1; + memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf)); + adapter->bcn_buf_end = adapter->bcn_buf; + adapter->multiple_dtim = 1; adapter->local_listen_interval = 0; /* default value in firmware @@ -307,6 +326,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) del_timer(&adapter->cmd_timer); dev_dbg(adapter->dev, "info: free scan table\n"); + kfree(adapter->scan_table); + adapter->scan_table = NULL; adapter->if_ops.cleanup_if(adapter); diff --git a/trunk/drivers/net/wireless/mwifiex/join.c b/trunk/drivers/net/wireless/mwifiex/join.c index 62b4c2938608..644e2e405cb5 100644 --- a/trunk/drivers/net/wireless/mwifiex/join.c +++ b/trunk/drivers/net/wireless/mwifiex/join.c @@ -147,12 +147,13 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, u8 *ptr = rate1, *tmp; u32 i, j; - tmp = kmemdup(rate1, rate1_size, GFP_KERNEL); + tmp = kmalloc(rate1_size, GFP_KERNEL); if (!tmp) { dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); return -ENOMEM; } + memcpy(tmp, rate1, rate1_size); memset(rate1, 0, rate1_size); for (i = 0; rate2[i] && i < rate2_size; i++) { @@ -222,6 +223,32 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, return 0; } +/* + * This function updates the scan entry TSF timestamps to reflect + * a new association. + */ +static void +mwifiex_update_tsf_timestamps(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *new_bss_desc) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 table_idx; + long long new_tsf_base; + signed long long tsf_delta; + + memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base)); + + tsf_delta = new_tsf_base - new_bss_desc->network_tsf; + + dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, " + "0x%016llx -> 0x%016llx\n", + new_bss_desc->network_tsf, new_tsf_base); + + for (table_idx = 0; table_idx < adapter->num_in_scan_table; + table_idx++) + adapter->scan_table[table_idx].network_tsf += tsf_delta; +} + /* * This function appends a WAPI IE. * @@ -612,6 +639,12 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, priv->curr_bss_params.band = (u8) bss_desc->bss_band; + /* + * Adjust the timestamps in the scan table to be relative to the newly + * associated AP's TSF + */ + mwifiex_update_tsf_timestamps(priv, bss_desc); + if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) priv->curr_bss_params.wmm_enabled = true; else diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index e6b6c0cfb63e..e6db0475ffa2 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -229,6 +229,21 @@ struct ieee_types_header { u8 len; } __packed; +struct ieee_obss_scan_param { + u16 obss_scan_passive_dwell; + u16 obss_scan_active_dwell; + u16 bss_chan_width_trigger_scan_int; + u16 obss_scan_passive_total; + u16 obss_scan_active_total; + u16 bss_width_chan_trans_delay; + u16 obss_scan_active_threshold; +} __packed; + +struct ieee_types_obss_scan_param { + struct ieee_types_header ieee_hdr; + struct ieee_obss_scan_param obss_scan; +} __packed; + #define MWIFIEX_SUPPORTED_RATES 14 #define MWIFIEX_SUPPORTED_RATES_EXT 32 @@ -276,6 +291,8 @@ struct mwifiex_bssdescriptor { u16 bss_co_2040_offset; u8 *bcn_ext_cap; u16 ext_cap_offset; + struct ieee_types_obss_scan_param *bcn_obss_scan; + u16 overlap_bss_offset; struct ieee_types_vendor_specific *bcn_wpa_ie; u16 wpa_offset; struct ieee_types_generic *bcn_rsn_ie; @@ -284,6 +301,8 @@ struct mwifiex_bssdescriptor { u16 wapi_offset; u8 *beacon_buf; u32 beacon_buf_size; + u32 beacon_buf_size_max; + }; struct mwifiex_current_bss_params { @@ -605,11 +624,15 @@ struct mwifiex_adapter { u32 scan_processing; u16 region_code; struct mwifiex_802_11d_domain_reg domain_reg; + struct mwifiex_bssdescriptor *scan_table; + u32 num_in_scan_table; u16 scan_probes; u32 scan_mode; u16 specific_scan_time; u16 active_scan_time; u16 passive_scan_time; + u8 bcn_buf[MAX_SCAN_BEACON_BUFFER]; + u8 *bcn_buf_end; u8 fw_bands; u8 adhoc_start_band; u8 config_bands; @@ -742,6 +765,13 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node); int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); +s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid, u8 *bssid, + u32 mode); +s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, + u32 mode); +int mwifiex_find_best_network(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *req_ssid_bssid); s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, struct mwifiex_802_11_ssid *ssid2); int mwifiex_associate(struct mwifiex_private *priv, @@ -752,6 +782,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); void mwifiex_reset_connect_state(struct mwifiex_private *priv); +void mwifiex_2040_coex_event(struct mwifiex_private *priv); u8 mwifiex_band_to_radio_type(u8 band); int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); int mwifiex_adhoc_start(struct mwifiex_private *priv, @@ -891,8 +922,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, struct net_device *dev); int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); -int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct mwifiex_802_11_ssid *req_ssid); +int mwifiex_bss_start(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid); int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, int cmd_type, struct mwifiex_ds_hs_cfg *hscfg); @@ -903,6 +934,8 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, struct mwifiex_ds_get_signal *signal); int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate); +int mwifiex_find_best_bss(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid); int mwifiex_request_scan(struct mwifiex_private *priv, struct mwifiex_802_11_ssid *req_ssid); int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, @@ -951,20 +984,12 @@ int mwifiex_main_process(struct mwifiex_adapter *); int mwifiex_bss_set_channel(struct mwifiex_private *, struct mwifiex_chan_freq_power *cfp); +int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *, + struct mwifiex_ssid_bssid *); int mwifiex_set_radio_band_cfg(struct mwifiex_private *, struct mwifiex_ds_band_cfg *); int mwifiex_get_bss_info(struct mwifiex_private *, struct mwifiex_bss_info *); -int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, - u8 *bssid, s32 rssi, u8 *ie_buf, - size_t ie_len, u16 beacon_period, - u16 cap_info_bitmap, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, - struct mwifiex_bssdescriptor *bss_entry, - u8 *ie_buf, u32 ie_len); -int mwifiex_check_network_compatibility(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c index 8d8588db1cd9..1fdfd41c3100 100644 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ b/trunk/drivers/net/wireless/mwifiex/scan.c @@ -171,6 +171,36 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len); } +/* + * Sends IOCTL request to get the best BSS. + * + * This function allocates the IOCTL request buffer, fills it + * with requisite parameters and calls the IOCTL handler. + */ +int mwifiex_find_best_bss(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid) +{ + struct mwifiex_ssid_bssid tmp_ssid_bssid; + u8 *mac; + + if (!ssid_bssid) + return -1; + + memcpy(&tmp_ssid_bssid, ssid_bssid, + sizeof(struct mwifiex_ssid_bssid)); + + if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) { + memcpy(ssid_bssid, &tmp_ssid_bssid, + sizeof(struct mwifiex_ssid_bssid)); + mac = (u8 *) &ssid_bssid->bssid; + dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s," + " %pM\n", ssid_bssid->ssid.ssid, mac); + return 0; + } + + return -1; +} + /* * Sends IOCTL request to start a scan with user configurations. * @@ -256,7 +286,8 @@ mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv, */ static bool mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) + struct mwifiex_bssdescriptor *bss_desc, + int index) { if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled @@ -267,9 +298,9 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, * LinkSys WRT54G && bss_desc->privacy */ ) { - dev_dbg(priv->adapter->dev, "info: %s: WPA:" + dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "EncMode=%#x privacy=%#x\n", __func__, + "EncMode=%#x privacy=%#x\n", __func__, index, (bss_desc->bcn_wpa_ie) ? (*(bss_desc->bcn_wpa_ie)). vend_hdr.element_id : 0, @@ -293,7 +324,8 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, */ static bool mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) + struct mwifiex_bssdescriptor *bss_desc, + int index) { if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled @@ -304,9 +336,9 @@ mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, * LinkSys WRT54G && bss_desc->privacy */ ) { - dev_dbg(priv->adapter->dev, "info: %s: WPA2: " + dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "EncMode=%#x privacy=%#x\n", __func__, + "EncMode=%#x privacy=%#x\n", __func__, index, (bss_desc->bcn_wpa_ie) ? (*(bss_desc->bcn_wpa_ie)). vend_hdr.element_id : 0, @@ -351,7 +383,8 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv, */ static bool mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) + struct mwifiex_bssdescriptor *bss_desc, + int index) { if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled @@ -362,9 +395,9 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, && priv->sec_info.encryption_mode && bss_desc->privacy) { dev_dbg(priv->adapter->dev, "info: %s: dynamic " - "WEP: wpa_ie=%#x wpa2_ie=%#x " + "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " "EncMode=%#x privacy=%#x\n", - __func__, + __func__, index, (bss_desc->bcn_wpa_ie) ? (*(bss_desc->bcn_wpa_ie)). vend_hdr.element_id : 0, @@ -397,41 +430,42 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, * Compatibility is not matched while roaming, except for mode. */ static s32 -mwifiex_is_network_compatible(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, u32 mode) +mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) { struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *bss_desc; + bss_desc = &adapter->scan_table[index]; bss_desc->disable_11n = false; /* Don't check for compatibility if roaming */ if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) - return 0; + return index; if (priv->wps.session_enable) { dev_dbg(adapter->dev, "info: return success directly in WPS period\n"); - return 0; + return index; } if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); - return 0; + return index; } if (bss_desc->bss_mode == mode) { if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { /* No security */ - return 0; + return index; } else if (mwifiex_is_network_compatible_for_static_wep(priv, bss_desc)) { /* Static WEP enabled */ dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); bss_desc->disable_11n = true; - return 0; - } else if (mwifiex_is_network_compatible_for_wpa(priv, - bss_desc)) { + return index; + } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, + index)) { /* WPA enabled */ if (((priv->adapter->config_bands & BAND_GN || priv->adapter->config_bands & BAND_AN) @@ -449,9 +483,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, return -1; } } - return 0; + return index; } else if (mwifiex_is_network_compatible_for_wpa2(priv, - bss_desc)) { + bss_desc, index)) { /* WPA2 enabled */ if (((priv->adapter->config_bands & BAND_GN || priv->adapter->config_bands & BAND_AN) @@ -469,22 +503,22 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, return -1; } } - return 0; + return index; } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, bss_desc)) { /* Ad-hoc AES enabled */ - return 0; + return index; } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, - bss_desc)) { + bss_desc, index)) { /* Dynamic WEP enabled */ - return 0; + return index; } /* Security doesn't match */ - dev_dbg(adapter->dev, "info: %s: failed: " + dev_dbg(adapter->dev, "info: %s: failed: index=%d " "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" "=%#x privacy=%#x\n", - __func__, + __func__, index, (bss_desc->bcn_wpa_ie) ? (*(bss_desc->bcn_wpa_ie)).vend_hdr. element_id : 0, @@ -503,6 +537,52 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, return -1; } +/* + * This function finds the best SSID in the scan list. + * + * It searches the scan table for the best SSID that also matches the current + * adapter network preference (mode, security etc.). + */ +static s32 +mwifiex_find_best_network_in_list(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 mode = priv->bss_mode; + s32 best_net = -1; + s32 best_rssi = 0; + u32 i; + + dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n", + adapter->num_in_scan_table); + + for (i = 0; i < adapter->num_in_scan_table; i++) { + switch (mode) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + if (mwifiex_is_network_compatible(priv, i, mode) >= 0) { + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table[i].rssi); + best_net = i; + } + } + break; + case NL80211_IFTYPE_UNSPECIFIED: + default: + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter->scan_table[i]. + rssi); + best_net = i; + } + break; + } + } + + return best_net; +} + /* * This function creates a channel list for the driver to scan, based * on region/band information. @@ -1081,13 +1161,34 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, } /* - * This function parses provided beacon buffer and updates - * respective fields in bss descriptor structure. + * This function interprets a BSS scan response returned from the firmware. + * + * The various fixed fields and IEs are parsed and passed back for a BSS + * probe response or beacon from scan command. Information is recorded as + * needed in the scan table for that entry. + * + * The following IE types are recognized and parsed - + * - SSID + * - Supported rates + * - FH parameters set + * - DS parameters set + * - CF parameters set + * - IBSS parameters set + * - ERP information + * - Extended supported rates + * - Vendor specific (221) + * - RSN IE + * - WAPI IE + * - HT capability + * - HT operation + * - BSS Coexistence 20/40 + * - Extended capability + * - Overlapping BSS scan parameters */ -int -mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, - struct mwifiex_bssdescriptor *bss_entry, - u8 *ie_buf, u32 ie_len) +static int +mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, + struct mwifiex_bssdescriptor *bss_entry, + u8 **beacon_info, u32 *bytes_left) { int ret = 0; u8 element_id; @@ -1095,43 +1196,135 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct ieee_types_ds_param_set *ds_param_set; struct ieee_types_cf_param_set *cf_param_set; struct ieee_types_ibss_param_set *ibss_param_set; + __le16 beacon_interval; + __le16 capabilities; u8 *current_ptr; u8 *rate; u8 element_len; u16 total_ie_len; u8 bytes_to_copy; u8 rate_size; + u16 beacon_size; u8 found_data_rate_ie; - u32 bytes_left; + u32 bytes_left_for_current_beacon; struct ieee_types_vendor_specific *vendor_ie; const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; found_data_rate_ie = false; rate_size = 0; - current_ptr = ie_buf; - bytes_left = ie_len; - bss_entry->beacon_buf = ie_buf; - bss_entry->beacon_buf_size = ie_len; + beacon_size = 0; + + if (*bytes_left >= sizeof(beacon_size)) { + /* Extract & convert beacon size from the command buffer */ + memcpy(&beacon_size, *beacon_info, sizeof(beacon_size)); + *bytes_left -= sizeof(beacon_size); + *beacon_info += sizeof(beacon_size); + } + + if (!beacon_size || beacon_size > *bytes_left) { + *beacon_info += *bytes_left; + *bytes_left = 0; + return -1; + } + + /* Initialize the current working beacon pointer for this BSS + iteration */ + current_ptr = *beacon_info; + + /* Advance the return beacon pointer past the current beacon */ + *beacon_info += beacon_size; + *bytes_left -= beacon_size; + + bytes_left_for_current_beacon = beacon_size; + + memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN); + dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n", + bss_entry->mac_address); + + current_ptr += ETH_ALEN; + bytes_left_for_current_beacon -= ETH_ALEN; + + if (bytes_left_for_current_beacon < 12) { + dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); + return -1; + } + + /* + * Next 4 fields are RSSI, time stamp, beacon interval, + * and capability information + */ + + /* RSSI is 1 byte long */ + bss_entry->rssi = (s32) (*current_ptr); + dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr); + current_ptr += 1; + bytes_left_for_current_beacon -= 1; + + /* + * The RSSI is not part of the beacon/probe response. After we have + * advanced current_ptr past the RSSI field, save the remaining + * data for use at the application layer + */ + bss_entry->beacon_buf = current_ptr; + bss_entry->beacon_buf_size = bytes_left_for_current_beacon; + + /* Time stamp is 8 bytes long */ + memcpy(bss_entry->time_stamp, current_ptr, 8); + current_ptr += 8; + bytes_left_for_current_beacon -= 8; + + /* Beacon interval is 2 bytes long */ + memcpy(&beacon_interval, current_ptr, 2); + bss_entry->beacon_period = le16_to_cpu(beacon_interval); + current_ptr += 2; + bytes_left_for_current_beacon -= 2; + + /* Capability information is 2 bytes long */ + memcpy(&capabilities, current_ptr, 2); + dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", + capabilities); + bss_entry->cap_info_bitmap = le16_to_cpu(capabilities); + current_ptr += 2; + bytes_left_for_current_beacon -= 2; + + /* Rest of the current buffer are IE's */ + dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", + bytes_left_for_current_beacon); + + if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { + dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n"); + bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; + } else { + bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; + } + + if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS) + bss_entry->bss_mode = NL80211_IFTYPE_ADHOC; + else + bss_entry->bss_mode = NL80211_IFTYPE_STATION; + /* Process variable IE */ - while (bytes_left >= 2) { + while (bytes_left_for_current_beacon >= 2) { element_id = *current_ptr; element_len = *(current_ptr + 1); total_ie_len = element_len + sizeof(struct ieee_types_header); - if (bytes_left < total_ie_len) { + if (bytes_left_for_current_beacon < total_ie_len) { dev_err(adapter->dev, "err: InterpretIE: in processing" " IE, bytes left < IE length\n"); - return -1; + bytes_left_for_current_beacon = 0; + ret = -1; + continue; } switch (element_id) { case WLAN_EID_SSID: bss_entry->ssid.ssid_len = element_len; memcpy(bss_entry->ssid.ssid, (current_ptr + 2), element_len); - dev_dbg(adapter->dev, "info: InterpretIE: ssid: " - "%-32s\n", bss_entry->ssid.ssid); + dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", + bss_entry->ssid.ssid); break; case WLAN_EID_SUPP_RATES: @@ -1278,6 +1471,13 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, sizeof(struct ieee_types_header) - bss_entry->beacon_buf); break; + case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: + bss_entry->bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + current_ptr; + bss_entry->overlap_bss_offset = (u16) (current_ptr - + bss_entry->beacon_buf); + break; default: break; } @@ -1285,12 +1485,576 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, current_ptr += element_len + 2; /* Need to account for IE ID and IE Len */ - bytes_left -= (element_len + 2); + bytes_left_for_current_beacon -= (element_len + 2); - } /* while (bytes_left > 2) */ + } /* while (bytes_left_for_current_beacon > 2) */ return ret; } +/* + * This function adjusts the pointers used in beacon buffers to reflect + * shifts. + * + * The memory allocated for beacon buffers is of fixed sizes where all the + * saved beacons must be stored. New beacons are added in the free portion + * of this memory, space permitting; while duplicate beacon buffers are + * placed at the same start location. However, since duplicate beacon + * buffers may not match the size of the old one, all the following buffers + * in the memory must be shifted to either make space, or to fill up freed + * up space. + * + * This function is used to update the beacon buffer pointers that are past + * an existing beacon buffer that is updated with a new one of different + * size. The pointers are shifted by a fixed amount, either forward or + * backward. + * + * the following pointers in every affected beacon buffers are changed, if + * present - + * - WPA IE pointer + * - RSN IE pointer + * - WAPI IE pointer + * - HT capability IE pointer + * - HT information IE pointer + * - BSS coexistence 20/40 IE pointer + * - Extended capability IE pointer + * - Overlapping BSS scan parameter IE pointer + */ +static void +mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance, + u8 *bcn_store, u32 rem_bcn_size, + u32 num_of_ent) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 adj_idx; + for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) { + if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) { + + if (advance) + adapter->scan_table[adj_idx].beacon_buf += + rem_bcn_size; + else + adapter->scan_table[adj_idx].beacon_buf -= + rem_bcn_size; + + if (adapter->scan_table[adj_idx].bcn_wpa_ie) + adapter->scan_table[adj_idx].bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].wpa_offset); + if (adapter->scan_table[adj_idx].bcn_rsn_ie) + adapter->scan_table[adj_idx].bcn_rsn_ie = + (struct ieee_types_generic *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].rsn_offset); + if (adapter->scan_table[adj_idx].bcn_wapi_ie) + adapter->scan_table[adj_idx].bcn_wapi_ie = + (struct ieee_types_generic *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].wapi_offset); + if (adapter->scan_table[adj_idx].bcn_ht_cap) + adapter->scan_table[adj_idx].bcn_ht_cap = + (struct ieee80211_ht_cap *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ht_cap_offset); + + if (adapter->scan_table[adj_idx].bcn_ht_info) + adapter->scan_table[adj_idx].bcn_ht_info = + (struct ieee80211_ht_info *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ht_info_offset); + if (adapter->scan_table[adj_idx].bcn_bss_co_2040) + adapter->scan_table[adj_idx].bcn_bss_co_2040 = + (u8 *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].bss_co_2040_offset); + if (adapter->scan_table[adj_idx].bcn_ext_cap) + adapter->scan_table[adj_idx].bcn_ext_cap = + (u8 *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].ext_cap_offset); + if (adapter->scan_table[adj_idx].bcn_obss_scan) + adapter->scan_table[adj_idx].bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (adapter->scan_table[adj_idx].beacon_buf + + adapter->scan_table[adj_idx].overlap_bss_offset); + } + } +} + +/* + * This function updates the pointers used in beacon buffer for given bss + * descriptor to reflect shifts + * + * Following pointers are updated + * - WPA IE pointer + * - RSN IE pointer + * - WAPI IE pointer + * - HT capability IE pointer + * - HT information IE pointer + * - BSS coexistence 20/40 IE pointer + * - Extended capability IE pointer + * - Overlapping BSS scan parameter IE pointer + */ +static void +mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon) +{ + if (beacon->bcn_wpa_ie) + beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *) + (beacon->beacon_buf + beacon->wpa_offset); + if (beacon->bcn_rsn_ie) + beacon->bcn_rsn_ie = (struct ieee_types_generic *) + (beacon->beacon_buf + beacon->rsn_offset); + if (beacon->bcn_wapi_ie) + beacon->bcn_wapi_ie = (struct ieee_types_generic *) + (beacon->beacon_buf + beacon->wapi_offset); + if (beacon->bcn_ht_cap) + beacon->bcn_ht_cap = (struct ieee80211_ht_cap *) + (beacon->beacon_buf + beacon->ht_cap_offset); + if (beacon->bcn_ht_info) + beacon->bcn_ht_info = (struct ieee80211_ht_info *) + (beacon->beacon_buf + beacon->ht_info_offset); + if (beacon->bcn_bss_co_2040) + beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf + + beacon->bss_co_2040_offset); + if (beacon->bcn_ext_cap) + beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf + + beacon->ext_cap_offset); + if (beacon->bcn_obss_scan) + beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *) + (beacon->beacon_buf + beacon->overlap_bss_offset); +} + +/* + * This function stores a beacon or probe response for a BSS returned + * in the scan. + * + * This stores a new scan response or an update for a previous scan response. + * New entries need to verify that they do not exceed the total amount of + * memory allocated for the table. + * + * Replacement entries need to take into consideration the amount of space + * currently allocated for the beacon/probe response and adjust the entry + * as needed. + * + * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved + * for an entry in case it is a beacon since a probe response for the + * network will by larger per the standard. This helps to reduce the + * amount of memory copying to fit a new probe response into an entry + * already occupied by a network's previously stored beacon. + */ +static void +mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv, + u32 beacon_idx, u32 num_of_ent, + struct mwifiex_bssdescriptor *new_beacon) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 *bcn_store; + u32 new_bcn_size; + u32 old_bcn_size; + u32 bcn_space; + + if (adapter->scan_table[beacon_idx].beacon_buf) { + + new_bcn_size = new_beacon->beacon_buf_size; + old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size; + bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max; + bcn_store = adapter->scan_table[beacon_idx].beacon_buf; + + /* Set the max to be the same as current entry unless changed + below */ + new_beacon->beacon_buf_size_max = bcn_space; + if (new_bcn_size == old_bcn_size) { + /* + * Beacon is the same size as the previous entry. + * Replace the previous contents with the scan result + */ + memcpy(bcn_store, new_beacon->beacon_buf, + new_beacon->beacon_buf_size); + + } else if (new_bcn_size <= bcn_space) { + /* + * New beacon size will fit in the amount of space + * we have previously allocated for it + */ + + /* Copy the new beacon buffer entry over the old one */ + memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); + + /* + * If the old beacon size was less than the maximum + * we had alloted for the entry, and the new entry + * is even smaller, reset the max size to the old + * beacon entry and compress the storage space + * (leaving a new pad space of (old_bcn_size - + * new_bcn_size). + */ + if (old_bcn_size < bcn_space + && new_bcn_size <= old_bcn_size) { + /* + * Old Beacon size is smaller than the alloted + * storage size. Shrink the alloted storage + * space. + */ + dev_dbg(adapter->dev, "info: AppControl:" + " smaller duplicate beacon " + "(%d), old = %d, new = %d, space = %d," + "left = %d\n", + beacon_idx, old_bcn_size, new_bcn_size, + bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* + * memmove (since the memory overlaps) the + * data after the beacon we just stored to the + * end of the current beacon. This cleans up + * any unused space the old larger beacon was + * using in the buffer + */ + memmove(bcn_store + old_bcn_size, + bcn_store + bcn_space, + adapter->bcn_buf_end - (bcn_store + + bcn_space)); + + /* + * Decrement the end pointer by the difference + * between the old larger size and the new + * smaller size since we are using less space + * due to the new beacon being smaller + */ + adapter->bcn_buf_end -= + (bcn_space - old_bcn_size); + + /* Set the maximum storage size to the old + beacon size */ + new_beacon->beacon_buf_size_max = old_bcn_size; + + /* Adjust beacon buffer pointers that are past + the current */ + mwifiex_adjust_beacon_buffer_ptrs(priv, 0, + bcn_store, (bcn_space - old_bcn_size), + num_of_ent); + } + } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space) + < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) { + /* + * Beacon is larger than space previously allocated + * (bcn_space) and there is enough space left in the + * beaconBuffer to store the additional data + */ + dev_dbg(adapter->dev, "info: AppControl:" + " larger duplicate beacon (%d), " + "old = %d, new = %d, space = %d, left = %d\n", + beacon_idx, old_bcn_size, new_bcn_size, + bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* + * memmove (since the memory overlaps) the data + * after the beacon we just stored to the end of + * the current beacon. This moves the data for + * the beacons after this further in memory to + * make space for the new larger beacon we are + * about to copy in. + */ + memmove(bcn_store + new_bcn_size, + bcn_store + bcn_space, + adapter->bcn_buf_end - (bcn_store + bcn_space)); + + /* Copy the new beacon buffer entry over the old one */ + memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); + + /* Move the beacon end pointer by the amount of new + beacon data we are adding */ + adapter->bcn_buf_end += (new_bcn_size - bcn_space); + + /* + * This entry is bigger than the alloted max space + * previously reserved. Increase the max space to + * be equal to the new beacon size + */ + new_beacon->beacon_buf_size_max = new_bcn_size; + + /* Adjust beacon buffer pointers that are past the + current */ + mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store, + (new_bcn_size - bcn_space), + num_of_ent); + } else { + /* + * Beacon is larger than the previously allocated space, + * but there is not enough free space to store the + * additional data. + */ + dev_err(adapter->dev, "AppControl: larger duplicate " + " beacon (%d), old = %d new = %d, space = %d," + " left = %d\n", beacon_idx, old_bcn_size, + new_bcn_size, bcn_space, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - adapter->bcn_buf))); + + /* Storage failure, keep old beacon intact */ + new_beacon->beacon_buf_size = old_bcn_size; + if (new_beacon->bcn_wpa_ie) + new_beacon->wpa_offset = + adapter->scan_table[beacon_idx]. + wpa_offset; + if (new_beacon->bcn_rsn_ie) + new_beacon->rsn_offset = + adapter->scan_table[beacon_idx]. + rsn_offset; + if (new_beacon->bcn_wapi_ie) + new_beacon->wapi_offset = + adapter->scan_table[beacon_idx]. + wapi_offset; + if (new_beacon->bcn_ht_cap) + new_beacon->ht_cap_offset = + adapter->scan_table[beacon_idx]. + ht_cap_offset; + if (new_beacon->bcn_ht_info) + new_beacon->ht_info_offset = + adapter->scan_table[beacon_idx]. + ht_info_offset; + if (new_beacon->bcn_bss_co_2040) + new_beacon->bss_co_2040_offset = + adapter->scan_table[beacon_idx]. + bss_co_2040_offset; + if (new_beacon->bcn_ext_cap) + new_beacon->ext_cap_offset = + adapter->scan_table[beacon_idx]. + ext_cap_offset; + if (new_beacon->bcn_obss_scan) + new_beacon->overlap_bss_offset = + adapter->scan_table[beacon_idx]. + overlap_bss_offset; + } + /* Point the new entry to its permanent storage space */ + new_beacon->beacon_buf = bcn_store; + mwifiex_update_beacon_buffer_ptrs(new_beacon); + } else { + /* + * No existing beacon data exists for this entry, check to see + * if we can fit it in the remaining space + */ + if (adapter->bcn_buf_end + new_beacon->beacon_buf_size + + SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf + + sizeof(adapter->bcn_buf))) { + + /* + * Copy the beacon buffer data from the local entry to + * the adapter dev struct buffer space used to store + * the raw beacon data for each entry in the scan table + */ + memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf, + new_beacon->beacon_buf_size); + + /* Update the beacon ptr to point to the table save + area */ + new_beacon->beacon_buf = adapter->bcn_buf_end; + new_beacon->beacon_buf_size_max = + (new_beacon->beacon_buf_size + + SCAN_BEACON_ENTRY_PAD); + + mwifiex_update_beacon_buffer_ptrs(new_beacon); + + /* Increment the end pointer by the size reserved */ + adapter->bcn_buf_end += new_beacon->beacon_buf_size_max; + + dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]" + " sz=%03d, used = %04d, left = %04d\n", + beacon_idx, + new_beacon->beacon_buf_size, + (int)(adapter->bcn_buf_end - adapter->bcn_buf), + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + } else { + /* No space for new beacon */ + dev_dbg(adapter->dev, "info: AppControl: no space for" + " beacon (%d): %pM sz=%03d, left=%03d\n", + beacon_idx, new_beacon->mac_address, + new_beacon->beacon_buf_size, + (int)(sizeof(adapter->bcn_buf) - + (adapter->bcn_buf_end - + adapter->bcn_buf))); + + /* Storage failure; clear storage records for this + bcn */ + new_beacon->beacon_buf = NULL; + new_beacon->beacon_buf_size = 0; + new_beacon->beacon_buf_size_max = 0; + new_beacon->bcn_wpa_ie = NULL; + new_beacon->wpa_offset = 0; + new_beacon->bcn_rsn_ie = NULL; + new_beacon->rsn_offset = 0; + new_beacon->bcn_wapi_ie = NULL; + new_beacon->wapi_offset = 0; + new_beacon->bcn_ht_cap = NULL; + new_beacon->ht_cap_offset = 0; + new_beacon->bcn_ht_info = NULL; + new_beacon->ht_info_offset = 0; + new_beacon->bcn_bss_co_2040 = NULL; + new_beacon->bss_co_2040_offset = 0; + new_beacon->bcn_ext_cap = NULL; + new_beacon->ext_cap_offset = 0; + new_beacon->bcn_obss_scan = NULL; + new_beacon->overlap_bss_offset = 0; + } + } +} + +/* + * This function restores a beacon buffer of the current BSS descriptor. + */ +static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *curr_bss = + &priv->curr_bss_params.bss_descriptor; + unsigned long flags; + + if (priv->curr_bcn_buf && + ((adapter->bcn_buf_end + priv->curr_bcn_size) < + (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) { + spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); + + /* restore the current beacon buffer */ + memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf, + priv->curr_bcn_size); + curr_bss->beacon_buf = adapter->bcn_buf_end; + curr_bss->beacon_buf_size = priv->curr_bcn_size; + adapter->bcn_buf_end += priv->curr_bcn_size; + + /* adjust the pointers in the current BSS descriptor */ + if (curr_bss->bcn_wpa_ie) + curr_bss->bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (curr_bss->beacon_buf + + curr_bss->wpa_offset); + + if (curr_bss->bcn_rsn_ie) + curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) + (curr_bss->beacon_buf + + curr_bss->rsn_offset); + + if (curr_bss->bcn_ht_cap) + curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) + (curr_bss->beacon_buf + + curr_bss->ht_cap_offset); + + if (curr_bss->bcn_ht_info) + curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) + (curr_bss->beacon_buf + + curr_bss->ht_info_offset); + + if (curr_bss->bcn_bss_co_2040) + curr_bss->bcn_bss_co_2040 = + (u8 *) (curr_bss->beacon_buf + + curr_bss->bss_co_2040_offset); + + if (curr_bss->bcn_ext_cap) + curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf + + curr_bss->ext_cap_offset); + + if (curr_bss->bcn_obss_scan) + curr_bss->bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (curr_bss->beacon_buf + + curr_bss->overlap_bss_offset); + + spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); + + dev_dbg(adapter->dev, "info: current beacon restored %d\n", + priv->curr_bcn_size); + } else { + dev_warn(adapter->dev, + "curr_bcn_buf not saved or bcn_buf has no space\n"); + } +} + +/* + * This function post processes the scan table after a new scan command has + * completed. + * + * It inspects each entry of the scan table and tries to find an entry that + * matches with our current associated/joined network from the scan. If + * one is found, the stored copy of the BSS descriptor of our current network + * is updated. + * + * It also debug dumps the current scan table contents after processing is over. + */ +static void +mwifiex_process_scan_results(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 j; + u32 i; + unsigned long flags; + + if (priv->media_connected) { + + j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params. + bss_descriptor.ssid, + priv->curr_bss_params. + bss_descriptor.mac_address, + priv->bss_mode); + + if (j >= 0) { + spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); + priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL; + priv->curr_bss_params.bss_descriptor.wpa_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL; + priv->curr_bss_params.bss_descriptor.rsn_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; + priv->curr_bss_params.bss_descriptor.wapi_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; + priv->curr_bss_params.bss_descriptor.ht_cap_offset = + 0; + priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; + priv->curr_bss_params.bss_descriptor.ht_info_offset = + 0; + priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = + NULL; + priv->curr_bss_params.bss_descriptor. + bss_co_2040_offset = 0; + priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; + priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; + priv->curr_bss_params.bss_descriptor. + bcn_obss_scan = NULL; + priv->curr_bss_params.bss_descriptor. + overlap_bss_offset = 0; + priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; + priv->curr_bss_params.bss_descriptor.beacon_buf_size = + 0; + priv->curr_bss_params.bss_descriptor. + beacon_buf_size_max = 0; + + dev_dbg(adapter->dev, "info: Found current ssid/bssid" + " in list @ index #%d\n", j); + /* Make a copy of current BSSID descriptor */ + memcpy(&priv->curr_bss_params.bss_descriptor, + &adapter->scan_table[j], + sizeof(priv->curr_bss_params.bss_descriptor)); + + mwifiex_save_curr_bcn(priv); + spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); + + } else { + mwifiex_restore_curr_bcn(priv); + } + } + + for (i = 0; i < adapter->num_in_scan_table; i++) + dev_dbg(adapter->dev, "info: scan:(%02d) %pM " + "RSSI[%03d], SSID[%s]\n", + i, adapter->scan_table[i].mac_address, + (s32) adapter->scan_table[i].rssi, + adapter->scan_table[i].ssid.ssid); +} + /* * This function converts radio type scan parameter to a band configuration * to be used in join command. @@ -1307,6 +2071,175 @@ mwifiex_radio_type_to_band(u8 radio_type) } } +/* + * This function deletes a specific indexed entry from the scan table. + * + * This also compacts the remaining entries and adjusts any buffering + * of beacon/probe response data if needed. + */ +static void +mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u32 del_idx; + u32 beacon_buf_adj; + u8 *beacon_buf; + + /* + * Shift the saved beacon buffer data for the scan table back over the + * entry being removed. Update the end of buffer pointer. Save the + * deleted buffer allocation size for pointer adjustments for entries + * compacted after the deleted index. + */ + beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max; + + dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer " + "removal = %d bytes\n", table_idx, beacon_buf_adj); + + /* Check if the table entry had storage allocated for its beacon */ + if (beacon_buf_adj) { + beacon_buf = adapter->scan_table[table_idx].beacon_buf; + + /* + * Remove the entry's buffer space, decrement the table end + * pointer by the amount we are removing + */ + adapter->bcn_buf_end -= beacon_buf_adj; + + dev_dbg(adapter->dev, "info: scan: delete entry %d," + " compact data: %p <- %p (sz = %d)\n", + table_idx, beacon_buf, + beacon_buf + beacon_buf_adj, + (int)(adapter->bcn_buf_end - beacon_buf)); + + /* + * Compact data storage. Copy all data after the deleted + * entry's end address (beacon_buf + beacon_buf_adj) back + * to the original start address (beacon_buf). + * + * Scan table entries affected by the move will have their + * entry pointer adjusted below. + * + * Use memmove since the dest/src memory regions overlap. + */ + memmove(beacon_buf, beacon_buf + beacon_buf_adj, + adapter->bcn_buf_end - beacon_buf); + } + + dev_dbg(adapter->dev, + "info: Scan: Delete Entry %d, num_in_scan_table = %d\n", + table_idx, adapter->num_in_scan_table); + + /* Shift all of the entries after the table_idx back by one, compacting + the table and removing the requested entry */ + for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table; + del_idx++) { + /* Copy the next entry over this one */ + memcpy(adapter->scan_table + del_idx, + adapter->scan_table + del_idx + 1, + sizeof(struct mwifiex_bssdescriptor)); + + /* + * Adjust this entry's pointer to its beacon buffer based on + * the removed/compacted entry from the deleted index. Don't + * decrement if the buffer pointer is NULL (no data stored for + * this entry). + */ + if (adapter->scan_table[del_idx].beacon_buf) { + adapter->scan_table[del_idx].beacon_buf -= + beacon_buf_adj; + if (adapter->scan_table[del_idx].bcn_wpa_ie) + adapter->scan_table[del_idx].bcn_wpa_ie = + (struct ieee_types_vendor_specific *) + (adapter->scan_table[del_idx]. + beacon_buf + + adapter->scan_table[del_idx]. + wpa_offset); + if (adapter->scan_table[del_idx].bcn_rsn_ie) + adapter->scan_table[del_idx].bcn_rsn_ie = + (struct ieee_types_generic *) + (adapter->scan_table[del_idx]. + beacon_buf + + adapter->scan_table[del_idx]. + rsn_offset); + if (adapter->scan_table[del_idx].bcn_wapi_ie) + adapter->scan_table[del_idx].bcn_wapi_ie = + (struct ieee_types_generic *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + wapi_offset); + if (adapter->scan_table[del_idx].bcn_ht_cap) + adapter->scan_table[del_idx].bcn_ht_cap = + (struct ieee80211_ht_cap *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ht_cap_offset); + + if (adapter->scan_table[del_idx].bcn_ht_info) + adapter->scan_table[del_idx].bcn_ht_info = + (struct ieee80211_ht_info *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ht_info_offset); + if (adapter->scan_table[del_idx].bcn_bss_co_2040) + adapter->scan_table[del_idx].bcn_bss_co_2040 = + (u8 *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + bss_co_2040_offset); + if (adapter->scan_table[del_idx].bcn_ext_cap) + adapter->scan_table[del_idx].bcn_ext_cap = + (u8 *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + ext_cap_offset); + if (adapter->scan_table[del_idx].bcn_obss_scan) + adapter->scan_table[del_idx]. + bcn_obss_scan = + (struct ieee_types_obss_scan_param *) + (adapter->scan_table[del_idx].beacon_buf + + adapter->scan_table[del_idx]. + overlap_bss_offset); + } + } + + /* The last entry is invalid now that it has been deleted or moved + back */ + memset(adapter->scan_table + adapter->num_in_scan_table - 1, + 0x00, sizeof(struct mwifiex_bssdescriptor)); + + adapter->num_in_scan_table--; +} + +/* + * This function deletes all occurrences of a given SSID from the scan table. + * + * This iterates through the scan table and deletes all entries that match + * the given SSID. It also compacts the remaining scan table entries. + */ +static int +mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *del_ssid) +{ + s32 table_idx = -1; + + dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n", + del_ssid->ssid); + + /* If the requested SSID is found in the table, delete it. Then keep + searching the table for multiple entires for the SSID until no + more are found */ + while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL, + NL80211_IFTYPE_UNSPECIFIED)) >= 0) { + dev_dbg(priv->adapter->dev, + "info: Scan: Delete SSID Entry: Found Idx = %d\n", + table_idx); + mwifiex_scan_delete_table_entry(priv, table_idx); + } + + return table_idx == -1 ? -1 : 0; +} + /* * This is an internal function used to start a scan based on an input * configuration. @@ -1325,6 +2258,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, struct mwifiex_ie_types_chan_list_param_set *chan_list_out; u32 buf_size; struct mwifiex_chan_scan_param_set *scan_chan_list; + u8 keep_previous_scan; u8 filtered_scan; u8 scan_current_chan_only; u8 max_chan_per_scan; @@ -1361,11 +2295,24 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, return -ENOMEM; } + keep_previous_scan = false; + mwifiex_scan_setup_scan_config(priv, user_scan_in, &scan_cfg_out->config, &chan_list_out, scan_chan_list, &max_chan_per_scan, &filtered_scan, &scan_current_chan_only); + if (user_scan_in) + keep_previous_scan = user_scan_in->keep_previous_scan; + + + if (!keep_previous_scan) { + memset(adapter->scan_table, 0x00, + sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP); + adapter->num_in_scan_table = 0; + adapter->bcn_buf_end = adapter->bcn_buf; + } + ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, &scan_cfg_out->config, chan_list_out, scan_chan_list); @@ -1431,107 +2378,6 @@ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, return 0; } -/* - * This function checks compatibility of requested network with current - * driver settings. - */ -int mwifiex_check_network_compatibility(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - int ret = -1; - - if (!bss_desc) - return -1; - - if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, - (u8) bss_desc->bss_band, (u16) bss_desc->channel))) { - switch (priv->bss_mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - ret = mwifiex_is_network_compatible(priv, bss_desc, - priv->bss_mode); - if (ret) - dev_err(priv->adapter->dev, "cannot find ssid " - "%s\n", bss_desc->ssid.ssid); - break; - default: - ret = 0; - } - } - - return ret; -} - -static int -mwifiex_update_curr_bss_params(struct mwifiex_private *priv, - u8 *bssid, s32 rssi, const u8 *ie_buf, - size_t ie_len, u16 beacon_period, u16 cap_info_bitmap) -{ - struct mwifiex_bssdescriptor *bss_desc = NULL; - int ret; - unsigned long flags; - u8 *beacon_ie; - - /* Allocate and fill new bss descriptor */ - bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), - GFP_KERNEL); - if (!bss_desc) { - dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); - return -ENOMEM; - } - - beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL); - if (!beacon_ie) { - dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); - return -ENOMEM; - } - - ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, - ie_len, beacon_period, - cap_info_bitmap, bss_desc); - if (ret) - goto done; - - ret = mwifiex_check_network_compatibility(priv, bss_desc); - if (ret) - goto done; - - /* Update current bss descriptor parameters */ - spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); - priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL; - priv->curr_bss_params.bss_descriptor.wpa_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL; - priv->curr_bss_params.bss_descriptor.rsn_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; - priv->curr_bss_params.bss_descriptor.wapi_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; - priv->curr_bss_params.bss_descriptor.ht_cap_offset = - 0; - priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; - priv->curr_bss_params.bss_descriptor.ht_info_offset = - 0; - priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = - NULL; - priv->curr_bss_params.bss_descriptor. - bss_co_2040_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; - priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; - priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; - priv->curr_bss_params.bss_descriptor.beacon_buf_size = - 0; - - /* Make a copy of current BSSID descriptor */ - memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, - sizeof(priv->curr_bss_params.bss_descriptor)); - mwifiex_save_curr_bcn(priv); - spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); - -done: - kfree(bss_desc); - kfree(beacon_ie); - return 0; -} - /* * This function handles the command response of scan. * @@ -1558,16 +2404,21 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; struct cmd_ctrl_node *cmd_node; struct host_cmd_ds_802_11_scan_rsp *scan_rsp; + struct mwifiex_bssdescriptor *bss_new_entry = NULL; struct mwifiex_ie_types_data *tlv_data; struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; u8 *bss_info; u32 scan_resp_size; u32 bytes_left; + u32 num_in_table; + u32 bss_idx; u32 idx; u32 tlv_buf_size; + long long tsf_val; struct mwifiex_chan_freq_power *cfp; struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; struct chan_band_param_set *chan_band; + u8 band; u8 is_bgscan_resp; unsigned long flags; @@ -1596,6 +2447,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, "info: SCAN_RESP: returned %d APs before parsing\n", scan_rsp->number_of_sets); + num_in_table = adapter->num_in_scan_table; bss_info = scan_rsp->bss_desc_and_tlv_buffer; /* @@ -1627,154 +2479,138 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, (struct mwifiex_ie_types_data **) &chan_band_tlv); - for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { - u8 bssid[ETH_ALEN]; - s32 rssi; - const u8 *ie_buf; - size_t ie_len; - int channel = -1; - u64 network_tsf = 0; - u16 beacon_size = 0; - u32 curr_bcn_bytes; - u32 freq; - u16 beacon_period; - u16 cap_info_bitmap; - u8 *current_ptr; - struct mwifiex_bcn_param *bcn_param; - - if (bytes_left >= sizeof(beacon_size)) { - /* Extract & convert beacon size from command buffer */ - memcpy(&beacon_size, bss_info, sizeof(beacon_size)); - bytes_left -= sizeof(beacon_size); - bss_info += sizeof(beacon_size); - } + /* + * Process each scan response returned (scan_rsp->number_of_sets). + * Save the information in the bss_new_entry and then insert into the + * driver scan table either as an update to an existing entry + * or as an addition at the end of the table + */ + bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor), + GFP_KERNEL); + if (!bss_new_entry) { + dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); + return -ENOMEM; + } - if (!beacon_size || beacon_size > bytes_left) { - bss_info += bytes_left; - bytes_left = 0; - return -1; + for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { + /* Zero out the bss_new_entry we are about to store info in */ + memset(bss_new_entry, 0x00, + sizeof(struct mwifiex_bssdescriptor)); + + if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, + &bss_info, + &bytes_left)) { + /* Error parsing/interpreting scan response, skipped */ + dev_err(adapter->dev, "SCAN_RESP: " + "mwifiex_interpret_bss_desc_with_ie " + "returned ERROR\n"); + continue; } - /* Initialize the current working beacon pointer for this BSS - * iteration */ - current_ptr = bss_info; - - /* Advance the return beacon pointer past the current beacon */ - bss_info += beacon_size; - bytes_left -= beacon_size; + /* Process the data fields and IEs returned for this BSS */ + dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", + bss_new_entry->mac_address); - curr_bcn_bytes = beacon_size; - - /* - * First 5 fields are bssid, RSSI, time stamp, beacon interval, - * and capability information - */ - if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) { - dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); - continue; - } - bcn_param = (struct mwifiex_bcn_param *)current_ptr; - current_ptr += sizeof(*bcn_param); - curr_bcn_bytes -= sizeof(*bcn_param); - - memcpy(bssid, bcn_param->bssid, ETH_ALEN); - - rssi = (s32) (bcn_param->rssi); - dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", - rssi); - - beacon_period = le16_to_cpu(bcn_param->beacon_period); - - cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); - dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", - cap_info_bitmap); - - /* Rest of the current buffer are IE's */ - ie_buf = current_ptr; - ie_len = curr_bcn_bytes; - dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP" - " = %d\n", curr_bcn_bytes); - - while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { - u8 element_id, element_len; - - element_id = *current_ptr; - element_len = *(current_ptr + 1); - if (curr_bcn_bytes < element_len + - sizeof(struct ieee_types_header)) { - dev_err(priv->adapter->dev, "%s: in processing" - " IE, bytes left < IE length\n", - __func__); - goto done; + /* Search the scan table for the same bssid */ + for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { + if (memcmp(bss_new_entry->mac_address, + adapter->scan_table[bss_idx].mac_address, + sizeof(bss_new_entry->mac_address))) { + continue; } - if (element_id == WLAN_EID_DS_PARAMS) { - channel = *(u8 *) (current_ptr + - sizeof(struct ieee_types_header)); + /* + * If the SSID matches as well, it is a + * duplicate of this entry. Keep the bss_idx + * set to this entry so we replace the old + * contents in the table + */ + if ((bss_new_entry->ssid.ssid_len + == adapter->scan_table[bss_idx]. ssid.ssid_len) + && (!memcmp(bss_new_entry->ssid.ssid, + adapter->scan_table[bss_idx].ssid.ssid, + bss_new_entry->ssid.ssid_len))) { + dev_dbg(adapter->dev, "info: SCAN_RESP:" + " duplicate of index: %d\n", bss_idx); break; } - - current_ptr += element_len + - sizeof(struct ieee_types_header); - curr_bcn_bytes -= element_len + - sizeof(struct ieee_types_header); + } + /* + * If the bss_idx is equal to the number of entries in + * the table, the new entry was not a duplicate; append + * it to the scan table + */ + if (bss_idx == num_in_table) { + /* Range check the bss_idx, keep it limited to + the last entry */ + if (bss_idx == MWIFIEX_MAX_AP) + bss_idx--; + else + num_in_table++; } + /* + * Save the beacon/probe response returned for later application + * retrieval. Duplicate beacon/probe responses are updated if + * possible + */ + mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx, + num_in_table, bss_new_entry); /* * If the TSF TLV was appended to the scan results, save this * entry's TSF value in the networkTSF field.The networkTSF is * the firmware's TSF value at the time the beacon or probe * response was received. */ - if (tsf_tlv) - memcpy(&network_tsf, - &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], - sizeof(network_tsf)); - - if (channel != -1) { - struct ieee80211_channel *chan; - u8 band; - - band = BAND_G; - if (chan_band_tlv) { - chan_band = - &chan_band_tlv->chan_band_param[idx]; - band = mwifiex_radio_type_to_band( - chan_band->radio_type - & (BIT(0) | BIT(1))); - } - - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211( - priv, (u8)band, (u16)channel); + if (tsf_tlv) { + memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] + , sizeof(tsf_val)); + memcpy(&bss_new_entry->network_tsf, &tsf_val, + sizeof(bss_new_entry->network_tsf)); + } + band = BAND_G; + if (chan_band_tlv) { + chan_band = &chan_band_tlv->chan_band_param[idx]; + band = mwifiex_radio_type_to_band(chan_band->radio_type + & (BIT(0) | BIT(1))); + } - freq = cfp ? cfp->freq : 0; + /* Save the band designation for this entry for use in join */ + bss_new_entry->bss_band = band; + cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, + (u8) bss_new_entry->bss_band, + (u16)bss_new_entry->channel); - chan = ieee80211_get_channel(priv->wdev->wiphy, freq); + if (cfp) + bss_new_entry->freq = cfp->freq; + else + bss_new_entry->freq = 0; - if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - cfg80211_inform_bss(priv->wdev->wiphy, chan, - bssid, network_tsf, cap_info_bitmap, - beacon_period, ie_buf, ie_len, rssi, - GFP_KERNEL); + /* Copy the locally created bss_new_entry to the scan table */ + memcpy(&adapter->scan_table[bss_idx], bss_new_entry, + sizeof(adapter->scan_table[bss_idx])); - if (priv->media_connected && !memcmp(bssid, - priv->curr_bss_params.bss_descriptor - .mac_address, ETH_ALEN)) - mwifiex_update_curr_bss_params(priv, - bssid, rssi, ie_buf, - ie_len, beacon_period, - cap_info_bitmap); - } - } else { - dev_dbg(adapter->dev, "missing BSS channel IE\n"); - } } + dev_dbg(adapter->dev, + "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", + scan_rsp->number_of_sets, + num_in_table - adapter->num_in_scan_table, num_in_table); + + /* Update the total number of BSSIDs in the scan table */ + adapter->num_in_scan_table = num_in_table; + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); if (list_empty(&adapter->scan_pending_q)) { spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + /* + * Process the resulting scan table: + * - Remove any bad ssids + * - Update our current BSS information from scan data + */ + mwifiex_process_scan_results(priv); /* Need to indicate IOCTL complete */ if (adapter->curr_cmd->wait_q_enabled) { @@ -1800,6 +2636,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, } done: + kfree((u8 *) bss_new_entry); return ret; } @@ -1825,6 +2662,141 @@ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) return 0; } +/* + * This function finds a SSID in the scan table. + * + * A BSSID may optionally be provided to qualify the SSID. + * For non-Auto mode, further check is made to make sure the + * BSS found in the scan table is compatible with the current + * settings of the driver. + */ +s32 +mwifiex_find_ssid_in_list(struct mwifiex_private *priv, + struct mwifiex_802_11_ssid *ssid, u8 *bssid, + u32 mode) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 net = -1, j; + u8 best_rssi = 0; + u32 i; + + dev_dbg(adapter->dev, "info: num of entries in table = %d\n", + adapter->num_in_scan_table); + + /* + * Loop through the table until the maximum is reached or until a match + * is found based on the bssid field comparison + */ + for (i = 0; + i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0)); + i++) { + if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) && + (!bssid + || !memcmp(adapter->scan_table[i].mac_address, bssid, + ETH_ALEN)) + && + (mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, (u8) adapter->scan_table[i].bss_band, + (u16) adapter->scan_table[i].channel))) { + switch (mode) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + j = mwifiex_is_network_compatible(priv, i, + mode); + + if (j >= 0) { + if (SCAN_RSSI + (adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table + [i].rssi); + net = i; + } + } else { + if (net == -1) + net = j; + } + break; + case NL80211_IFTYPE_UNSPECIFIED: + default: + /* + * Do not check compatibility if the mode + * requested is Auto/Unknown. Allows generic + * find to work without verifying against the + * Adapter security settings + */ + if (SCAN_RSSI(adapter->scan_table[i].rssi) > + best_rssi) { + best_rssi = SCAN_RSSI(adapter-> + scan_table[i].rssi); + net = i; + } + break; + } + } + } + + return net; +} + +/* + * This function finds a specific compatible BSSID in the scan list. + * + * This function loops through the scan table looking for a compatible + * match. If a BSSID matches, but the BSS is found to be not compatible + * the function ignores it and continues to search through the rest of + * the entries in case there is an AP with multiple SSIDs assigned to + * the same BSSID. + */ +s32 +mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, + u32 mode) +{ + struct mwifiex_adapter *adapter = priv->adapter; + s32 net = -1; + u32 i; + + if (!bssid) + return -1; + + dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n", + adapter->num_in_scan_table); + + /* + * Look through the scan table for a compatible match. The ret return + * variable will be equal to the index in the scan table (greater + * than zero) if the network is compatible. The loop will continue + * past a matched bssid that is not compatible in case there is an + * AP with multiple SSIDs assigned to the same BSSID + */ + for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) { + if (!memcmp + (adapter->scan_table[i].mac_address, bssid, ETH_ALEN) + && mwifiex_get_cfp_by_band_and_channel_from_cfg80211 + (priv, + (u8) adapter-> + scan_table[i]. + bss_band, + (u16) adapter-> + scan_table[i]. + channel)) { + switch (mode) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + net = mwifiex_is_network_compatible(priv, i, + mode); + break; + default: + net = i; + break; + } + } + } + + return net; +} + /* * This function inserts scan command node to the scan pending queue. */ @@ -1841,6 +2813,42 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv, spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); } +/* + * This function finds an AP with specific ssid in the scan list. + */ +int mwifiex_find_best_network(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *req_ssid_bssid) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *req_bss; + s32 i; + + memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); + + i = mwifiex_find_best_network_in_list(priv); + + if (i >= 0) { + req_bss = &adapter->scan_table[i]; + memcpy(&req_ssid_bssid->ssid, &req_bss->ssid, + sizeof(struct mwifiex_802_11_ssid)); + memcpy((u8 *) &req_ssid_bssid->bssid, + (u8 *) &req_bss->mac_address, ETH_ALEN); + + /* Make sure we are in the right mode */ + if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) + priv->bss_mode = req_bss->bss_mode; + } + + if (!req_ssid_bssid->ssid.ssid_len) + return -1; + + dev_dbg(adapter->dev, "info: Best network found = [%s], " + "[%pM]\n", req_ssid_bssid->ssid.ssid, + req_ssid_bssid->bssid); + + return 0; +} + /* * This function sends a scan command for all available channels to the * firmware, filtered on a specific SSID. @@ -1866,6 +2874,8 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, return ret; } + mwifiex_scan_delete_ssid_table_entry(priv, req_ssid); + scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); if (!scan_cfg) { dev_err(adapter->dev, "failed to alloc scan_cfg\n"); @@ -1874,6 +2884,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, req_ssid->ssid_len); + scan_cfg->keep_previous_scan = true; ret = mwifiex_scan_networks(priv, scan_cfg); @@ -1986,7 +2997,7 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) priv->curr_bcn_size = curr_bss->beacon_buf_size; kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size, + priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, GFP_KERNEL); if (!priv->curr_bcn_buf) { dev_err(priv->adapter->dev, @@ -1999,39 +3010,6 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) curr_bss->beacon_buf_size); dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", priv->curr_bcn_size); - - curr_bss->beacon_buf = priv->curr_bcn_buf; - - /* adjust the pointers in the current BSS descriptor */ - if (curr_bss->bcn_wpa_ie) - curr_bss->bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - (curr_bss->beacon_buf + - curr_bss->wpa_offset); - - if (curr_bss->bcn_rsn_ie) - curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) - (curr_bss->beacon_buf + - curr_bss->rsn_offset); - - if (curr_bss->bcn_ht_cap) - curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) - (curr_bss->beacon_buf + - curr_bss->ht_cap_offset); - - if (curr_bss->bcn_ht_info) - curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) - (curr_bss->beacon_buf + - curr_bss->ht_info_offset); - - if (curr_bss->bcn_bss_co_2040) - curr_bss->bcn_bss_co_2040 = - (u8 *) (curr_bss->beacon_buf + - curr_bss->bss_co_2040_offset); - - if (curr_bss->bcn_ext_cap) - curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf + - curr_bss->ext_cap_offset); } /* diff --git a/trunk/drivers/net/wireless/mwifiex/sta_event.c b/trunk/drivers/net/wireless/mwifiex/sta_event.c index f204810e8338..6e8b198490b0 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_event.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_event.c @@ -299,6 +299,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_BG_SCAN_REPORT: dev_dbg(adapter->dev, "event: BGS_REPORT\n"); + /* Clear the previous scan result */ + memset(adapter->scan_table, 0x00, + sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP); + adapter->num_in_scan_table = 0; + adapter->bcn_buf_end = adapter->bcn_buf; ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY, HostCmd_ACT_GEN_GET, 0, NULL); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index eb569fa9adba..fd764b3c6751 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -141,144 +141,91 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, return ret; } -/* - * This function fills bss descriptor structure using provided - * information. - */ -int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, - u8 *bssid, s32 rssi, u8 *ie_buf, - size_t ie_len, u16 beacon_period, - u16 cap_info_bitmap, - struct mwifiex_bssdescriptor *bss_desc) -{ - int ret; - - memcpy(bss_desc->mac_address, bssid, ETH_ALEN); - bss_desc->rssi = rssi; - bss_desc->beacon_buf = ie_buf; - bss_desc->beacon_buf_size = ie_len; - bss_desc->beacon_period = beacon_period; - bss_desc->cap_info_bitmap = cap_info_bitmap; - if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { - dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; - } else { - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; - } - if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS) - bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; - else - bss_desc->bss_mode = NL80211_IFTYPE_STATION; - - ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc, - ie_buf, ie_len); - - return ret; -} - /* * In Ad-Hoc mode, the IBSS is created if not found in scan list. * In both Ad-Hoc and infra mode, an deauthentication is performed * first. */ -int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct mwifiex_802_11_ssid *req_ssid) +int mwifiex_bss_start(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid) { int ret; struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc = NULL; - u8 *beacon_ie = NULL; + s32 i = -1; priv->scan_block = false; - - if (bss) { - /* Allocate and fill new bss descriptor */ - bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), - GFP_KERNEL); - if (!bss_desc) { - dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); - return -ENOMEM; - } - - beacon_ie = kmemdup(bss->information_elements, - bss->len_beacon_ies, GFP_KERNEL); - if (!beacon_ie) { - dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); - return -ENOMEM; - } - - ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, - beacon_ie, bss->len_beacon_ies, - bss->beacon_interval, - bss->capability, bss_desc); - if (ret) - goto done; - } + if (!ssid_bssid) + return -1; if (priv->bss_mode == NL80211_IFTYPE_STATION) { /* Infra mode */ ret = mwifiex_deauthenticate(priv, NULL); if (ret) - goto done; - - ret = mwifiex_check_network_compatibility(priv, bss_desc); - if (ret) - goto done; + return ret; - dev_dbg(adapter->dev, "info: SSID found in scan list ... " - "associating...\n"); + /* Search for the requested SSID in the scan table */ + if (ssid_bssid->ssid.ssid_len) + i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, + NULL, NL80211_IFTYPE_STATION); + else + i = mwifiex_find_bssid_in_list(priv, + (u8 *) &ssid_bssid->bssid, + NL80211_IFTYPE_STATION); + if (i < 0) + return -1; - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); + dev_dbg(adapter->dev, + "info: SSID found in scan list ... associating...\n"); /* Clear any past association response stored for * application retrieval */ priv->assoc_rsp_size = 0; - ret = mwifiex_associate(priv, bss_desc); - if (bss) - cfg80211_put_bss(bss); + ret = mwifiex_associate(priv, &adapter->scan_table[i]); + if (ret) + return ret; } else { /* Adhoc mode */ /* If the requested SSID matches current SSID, return */ - if (bss_desc && bss_desc->ssid.ssid_len && + if (ssid_bssid->ssid.ssid_len && (!mwifiex_ssid_cmp (&priv->curr_bss_params.bss_descriptor.ssid, - &bss_desc->ssid))) { - kfree(bss_desc); - kfree(beacon_ie); + &ssid_bssid->ssid))) return 0; - } /* Exit Adhoc mode first */ dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); ret = mwifiex_deauthenticate(priv, NULL); if (ret) - goto done; + return ret; priv->adhoc_is_link_sensed = false; - ret = mwifiex_check_network_compatibility(priv, bss_desc); - - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - - if (!ret) { + /* Search for the requested network in the scan table */ + if (ssid_bssid->ssid.ssid_len) + i = mwifiex_find_ssid_in_list(priv, + &ssid_bssid->ssid, NULL, + NL80211_IFTYPE_ADHOC); + else + i = mwifiex_find_bssid_in_list(priv, + (u8 *)&ssid_bssid->bssid, + NL80211_IFTYPE_ADHOC); + + if (i >= 0) { dev_dbg(adapter->dev, "info: network found in scan" " list. Joining...\n"); - ret = mwifiex_adhoc_join(priv, bss_desc); - if (bss) - cfg80211_put_bss(bss); + ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); + if (ret) + return ret; } else { dev_dbg(adapter->dev, "info: Network not found in " "the list, creating adhoc with ssid = %s\n", - req_ssid->ssid); - ret = mwifiex_adhoc_start(priv, req_ssid); + ssid_bssid->ssid.ssid); + ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid); + if (ret) + return ret; } } -done: - kfree(bss_desc); - kfree(beacon_ie); return ret; } @@ -626,6 +573,50 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, action, 0, channel); } +/* + * IOCTL request handler to find a particular BSS. + * + * The BSS can be searched with either a BSSID or a SSID. If none of + * these are provided, just the best BSS (best RSSI) is returned. + */ +int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, + struct mwifiex_ssid_bssid *ssid_bssid) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_bssdescriptor *bss_desc; + u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + u8 mac[ETH_ALEN]; + int i = 0; + + if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) { + i = mwifiex_find_bssid_in_list(priv, + (u8 *) ssid_bssid->bssid, + priv->bss_mode); + if (i < 0) { + memcpy(mac, ssid_bssid->bssid, sizeof(mac)); + dev_err(adapter->dev, "cannot find bssid %pM\n", mac); + return -1; + } + bss_desc = &adapter->scan_table[i]; + memcpy(&ssid_bssid->ssid, &bss_desc->ssid, + sizeof(struct mwifiex_802_11_ssid)); + } else if (ssid_bssid->ssid.ssid_len) { + i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL, + priv->bss_mode); + if (i < 0) { + dev_err(adapter->dev, "cannot find ssid %s\n", + ssid_bssid->ssid.ssid); + return -1; + } + bss_desc = &adapter->scan_table[i]; + memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN); + } else { + return mwifiex_find_best_network(priv, ssid_bssid); + } + + return 0; +} + /* * IOCTL request handler to change Ad-Hoc channel. * @@ -650,8 +641,6 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) struct mwifiex_bss_info bss_info; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; - struct cfg80211_bss *bss = NULL; - struct ieee80211_channel *chan; memset(&bss_info, 0, sizeof(bss_info)); @@ -687,20 +676,12 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) ret = -1; goto done; } + /* Start/Join Adhoc network */ + memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); + memcpy(&ssid_bssid.ssid, &bss_info.ssid, + sizeof(struct mwifiex_802_11_ssid)); - chan = __ieee80211_get_channel(priv->wdev->wiphy, - ieee80211_channel_to_frequency(channel, - priv->curr_bss_params.band)); - - /* Find the BSS we want using available scan results */ - bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, - bss_info.ssid.ssid, bss_info.ssid.ssid_len, - WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (!bss) - wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n", - bss_info.bssid); - - ret = mwifiex_bss_start(priv, bss, &bss_info.ssid); + ret = mwifiex_bss_start(priv, &ssid_bssid); done: return ret; } diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index ea1395aafa39..da36dbf8d871 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -4097,6 +4097,9 @@ static int mwl8k_set_key(struct ieee80211_hw *hw, if (rc) goto out; + + mwl8k_vif->is_hw_crypto_enabled = false; + } out: return rc; @@ -5501,14 +5504,6 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) /* Set rssi values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; - - /* - * Ask mac80211 to not to trigger PS mode - * based on PM bit of incoming frames. - */ - if (priv->ap_fw) - hw->flags |= IEEE80211_HW_AP_LINK_PS; - hw->vif_data_size = sizeof(struct mwl8k_vif); hw->sta_data_size = sizeof(struct mwl8k_sta); diff --git a/trunk/drivers/net/wireless/p54/eeprom.c b/trunk/drivers/net/wireless/p54/eeprom.c index 8b6f363b3f7d..54cc0bba66b9 100644 --- a/trunk/drivers/net/wireless/p54/eeprom.c +++ b/trunk/drivers/net/wireless/p54/eeprom.c @@ -145,7 +145,6 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev, static int p54_generate_band(struct ieee80211_hw *dev, struct p54_channel_list *list, - unsigned int *chan_num, enum ieee80211_band band) { struct p54_common *priv = dev->priv; @@ -191,14 +190,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, tmp->channels[j].band = chan->band; tmp->channels[j].center_freq = chan->freq; - priv->survey[*chan_num].channel = &tmp->channels[j]; - priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | - SURVEY_INFO_CHANNEL_TIME | - SURVEY_INFO_CHANNEL_TIME_BUSY | - SURVEY_INFO_CHANNEL_TIME_TX; - tmp->channels[j].hw_value = (*chan_num); j++; - (*chan_num)++; } if (j == 0) { @@ -271,7 +263,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; struct p54_channel_list *list; - unsigned int i, j, k, max_channel_num; + unsigned int i, j, max_channel_num; int ret = 0; u16 freq; @@ -291,13 +283,6 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) ret = -ENOMEM; goto free; } - priv->chan_num = max_channel_num; - priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num, - GFP_KERNEL); - if (!priv->survey) { - ret = -ENOMEM; - goto free; - } list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * @@ -336,9 +321,8 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) sort(list->channels, list->entries, sizeof(struct p54_channel_entry), p54_compare_channels, NULL); - k = 0; for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { - if (p54_generate_band(dev, list, &k, i) == 0) + if (p54_generate_band(dev, list, i) == 0) j++; } if (j == 0) { @@ -351,10 +335,6 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) kfree(list->channels); kfree(list); } - if (ret) { - kfree(priv->survey); - priv->survey = NULL; - } return ret; } @@ -873,12 +853,10 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) kfree(priv->output_limit); kfree(priv->curve_data); kfree(priv->rssi_db); - kfree(priv->survey); priv->iq_autocal = NULL; priv->output_limit = NULL; priv->curve_data = NULL; priv->rssi_db = NULL; - priv->survey = NULL; wiphy_err(dev->wiphy, "eeprom parse failed!\n"); return err; diff --git a/trunk/drivers/net/wireless/p54/fwio.c b/trunk/drivers/net/wireless/p54/fwio.c index 53a3408931be..b6a061cbbdec 100644 --- a/trunk/drivers/net/wireless/p54/fwio.c +++ b/trunk/drivers/net/wireless/p54/fwio.c @@ -385,7 +385,6 @@ int p54_setup_mac(struct p54_common *priv) setup->v2.osc_start_delay = cpu_to_le16(65535); } p54_tx(priv, skb); - priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE; return 0; } @@ -627,7 +626,6 @@ int p54_set_ps(struct p54_common *priv) psm->exclude[0] = WLAN_EID_TIM; p54_tx(priv, skb); - priv->phy_ps = mode != P54_PSM_CAM; return 0; } diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c index 726a9343f514..a5a6d9e647bb 100644 --- a/trunk/drivers/net/wireless/p54/main.c +++ b/trunk/drivers/net/wireless/p54/main.c @@ -204,11 +204,13 @@ static void p54_stop(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; int i; + mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->softled_state = 0; - cancel_delayed_work_sync(&priv->work); - mutex_lock(&priv->conf_mutex); p54_set_leds(priv); + + cancel_delayed_work_sync(&priv->work); + priv->stop(dev); skb_queue_purge(&priv->tx_pending); skb_queue_purge(&priv->tx_queue); @@ -276,42 +278,6 @@ static void p54_remove_interface(struct ieee80211_hw *dev, mutex_unlock(&priv->conf_mutex); } -static int p54_wait_for_stats(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int ret; - - priv->update_stats = true; - ret = p54_fetch_statistics(priv); - if (ret) - return ret; - - ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ); - if (ret == 0) - return -ETIMEDOUT; - - return 0; -} - -static void p54_reset_stats(struct p54_common *priv) -{ - struct ieee80211_channel *chan = priv->curchan; - - if (chan) { - struct survey_info *info = &priv->survey[chan->hw_value]; - - /* only reset channel statistics, don't touch .filled, etc. */ - info->channel_time = 0; - info->channel_time_busy = 0; - info->channel_time_tx = 0; - } - - priv->update_stats = true; - priv->survey_raw.active = 0; - priv->survey_raw.cca = 0; - priv->survey_raw.tx = 0; -} - static int p54_config(struct ieee80211_hw *dev, u32 changed) { int ret = 0; @@ -322,36 +288,19 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) priv->output_power = conf->power_level << 2; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - struct ieee80211_channel *oldchan; - WARN_ON(p54_wait_for_stats(dev)); - oldchan = priv->curchan; - priv->curchan = NULL; ret = p54_scan(priv, P54_SCAN_EXIT, 0); - if (ret) { - priv->curchan = oldchan; + if (ret) goto out; - } - /* - * TODO: Use the LM_SCAN_TRAP to determine the current - * operating channel. - */ - priv->curchan = priv->hw->conf.channel; - p54_reset_stats(priv); - WARN_ON(p54_fetch_statistics(priv)); } if (changed & IEEE80211_CONF_CHANGE_PS) { - WARN_ON(p54_wait_for_stats(dev)); ret = p54_set_ps(priv); if (ret) goto out; - WARN_ON(p54_wait_for_stats(dev)); } if (changed & IEEE80211_CONF_CHANGE_IDLE) { - WARN_ON(p54_wait_for_stats(dev)); ret = p54_setup_mac(priv); if (ret) goto out; - WARN_ON(p54_wait_for_stats(dev)); } out: @@ -435,9 +384,7 @@ static void p54_work(struct work_struct *work) * 2. cancel stuck frames / reset the device if necessary. */ - mutex_lock(&priv->conf_mutex); - WARN_ON_ONCE(p54_fetch_statistics(priv)); - mutex_unlock(&priv->conf_mutex); + p54_fetch_statistics(priv); } static int p54_get_stats(struct ieee80211_hw *dev, @@ -594,47 +541,16 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx, struct survey_info *survey) { struct p54_common *priv = dev->priv; - struct ieee80211_channel *chan; - int err, tries; - bool in_use = false; + struct ieee80211_conf *conf = &dev->conf; - if (idx >= priv->chan_num) + if (idx != 0) return -ENOENT; -#define MAX_TRIES 1 - for (tries = 0; tries < MAX_TRIES; tries++) { - chan = priv->curchan; - if (chan && chan->hw_value == idx) { - mutex_lock(&priv->conf_mutex); - err = p54_wait_for_stats(dev); - mutex_unlock(&priv->conf_mutex); - if (err) - return err; - - in_use = true; - } + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = clamp_t(s8, priv->noise, -128, 127); - memcpy(survey, &priv->survey[idx], sizeof(*survey)); - - if (in_use) { - /* test if the reported statistics are valid. */ - if (survey->channel_time != 0) { - survey->filled |= SURVEY_INFO_IN_USE; - } else { - /* - * hw/fw has not accumulated enough sample sets. - * Wait for 100ms, this ought to be enough to - * to get at least one non-null set of channel - * usage statistics. - */ - msleep(100); - continue; - } - } - return 0; - } - return -ETIMEDOUT; -#undef MAX_TRIES + return 0; } static unsigned int p54_flush_count(struct p54_common *priv) @@ -770,14 +686,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) mutex_init(&priv->conf_mutex); mutex_init(&priv->eeprom_mutex); - init_completion(&priv->stat_comp); init_completion(&priv->eeprom_comp); init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); memset(&priv->mc_maclist[0], ~0, ETH_ALEN); - priv->curchan = NULL; - p54_reset_stats(priv); return dev; } EXPORT_SYMBOL_GPL(p54_init_common); @@ -817,13 +730,11 @@ void p54_free_common(struct ieee80211_hw *dev) kfree(priv->curve_data); kfree(priv->rssi_db); kfree(priv->used_rxkeys); - kfree(priv->survey); priv->iq_autocal = NULL; priv->output_limit = NULL; priv->curve_data = NULL; priv->rssi_db = NULL; priv->used_rxkeys = NULL; - priv->survey = NULL; ieee80211_free_hw(dev); } EXPORT_SYMBOL_GPL(p54_free_common); diff --git a/trunk/drivers/net/wireless/p54/p54.h b/trunk/drivers/net/wireless/p54/p54.h index 452fa3a64aa1..799d05e12595 100644 --- a/trunk/drivers/net/wireless/p54/p54.h +++ b/trunk/drivers/net/wireless/p54/p54.h @@ -199,22 +199,6 @@ struct p54_common { u8 tx_diversity_mask; unsigned int output_power; struct p54_rssi_db_entry *cur_rssi; - struct ieee80211_channel *curchan; - struct survey_info *survey; - unsigned int chan_num; - struct completion stat_comp; - bool update_stats; - struct { - unsigned int timestamp; - unsigned int cached_cca; - unsigned int cached_tx; - unsigned int cached_rssi; - u64 active; - u64 cca; - u64 tx; - u64 rssi; - } survey_raw; - int noise; /* calibration, output power limit and rssi<->dBm conversation data */ struct pda_iq_autocal_entry *iq_autocal; @@ -236,8 +220,6 @@ struct p54_common { u32 basic_rate_mask; u16 aid; u8 coverage_class; - bool phy_idle; - bool phy_ps; bool powersave_override; __le32 beacon_req_id; struct completion beacon_comp; diff --git a/trunk/drivers/net/wireless/p54/p54spi.c b/trunk/drivers/net/wireless/p54/p54spi.c index f18df82eeb92..6d9204fef90b 100644 --- a/trunk/drivers/net/wireless/p54/p54spi.c +++ b/trunk/drivers/net/wireless/p54/p54spi.c @@ -41,6 +41,7 @@ #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ MODULE_FIRMWARE("3826.arm"); +MODULE_ALIAS("stlc45xx"); /* * gpios should be handled in board files and provided via platform data, @@ -737,4 +738,3 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter "); MODULE_ALIAS("spi:cx3110x"); MODULE_ALIAS("spi:p54spi"); -MODULE_ALIAS("spi:stlc45xx"); diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c index 2b97a89e7ff8..042842e704de 100644 --- a/trunk/drivers/net/wireless/p54/txrx.c +++ b/trunk/drivers/net/wireless/p54/txrx.c @@ -19,7 +19,6 @@ #include #include #include -#include #include @@ -508,8 +507,6 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) struct p54_hdr *hdr = (struct p54_hdr *) skb->data; struct p54_statistics *stats = (struct p54_statistics *) hdr->data; struct sk_buff *tmp; - struct ieee80211_channel *chan; - unsigned int i, rssi, tx, cca, dtime, dtotal, dcca, dtx, drssi, unit; u32 tsf32; if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) @@ -526,75 +523,8 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise)); - /* - * STSW450X LMAC API page 26 - 3.8 Statistics - * "The exact measurement period can be derived from the - * timestamp member". - */ - dtime = tsf32 - priv->survey_raw.timestamp; - - /* - * STSW450X LMAC API page 26 - 3.8.1 Noise histogram - * The LMAC samples RSSI, CCA and transmit state at regular - * periods (typically 8 times per 1k [as in 1024] usec). - */ - cca = le32_to_cpu(stats->sample_cca); - tx = le32_to_cpu(stats->sample_tx); - rssi = 0; - for (i = 0; i < ARRAY_SIZE(stats->sample_noise); i++) - rssi += le32_to_cpu(stats->sample_noise[i]); - - dcca = cca - priv->survey_raw.cached_cca; - drssi = rssi - priv->survey_raw.cached_rssi; - dtx = tx - priv->survey_raw.cached_tx; - dtotal = dcca + drssi + dtx; - - /* - * update statistics when more than a second is over since the - * last call, or when a update is badly needed. - */ - if (dtotal && (priv->update_stats || dtime >= USEC_PER_SEC) && - dtime >= dtotal) { - priv->survey_raw.timestamp = tsf32; - priv->update_stats = false; - unit = dtime / dtotal; - - if (dcca) { - priv->survey_raw.cca += dcca * unit; - priv->survey_raw.cached_cca = cca; - } - if (dtx) { - priv->survey_raw.tx += dtx * unit; - priv->survey_raw.cached_tx = tx; - } - if (drssi) { - priv->survey_raw.rssi += drssi * unit; - priv->survey_raw.cached_rssi = rssi; - } - - /* 1024 usec / 8 times = 128 usec / time */ - if (!(priv->phy_ps || priv->phy_idle)) - priv->survey_raw.active += dtotal * unit; - else - priv->survey_raw.active += (dcca + dtx) * unit; - } - - chan = priv->curchan; - if (chan) { - struct survey_info *survey = &priv->survey[chan->hw_value]; - survey->noise = clamp_t(s8, priv->noise, -128, 127); - survey->channel_time = priv->survey_raw.active; - survey->channel_time_tx = priv->survey_raw.tx; - survey->channel_time_busy = priv->survey_raw.tx + - priv->survey_raw.cca; - do_div(survey->channel_time, 1024); - do_div(survey->channel_time_tx, 1024); - do_div(survey->channel_time_busy, 1024); - } - tmp = p54_find_and_unlink_skb(priv, hdr->req_id); dev_kfree_skb_any(tmp); - complete(&priv->stat_comp); } static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800.h b/trunk/drivers/net/wireless/rt2x00/rt2800.h index 4778620347c4..c69a7d71f4ca 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800.h @@ -664,9 +664,6 @@ /* * LED_CFG: LED control - * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1) - * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1) - * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2) * color LED's: * 0: off * 1: blinking upon TX2 diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index a5ddb39ca4a0..ef67f6786a84 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size); rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : txdesc->u.ht.wcid); + txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, txdesc->length); rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); @@ -601,7 +601,7 @@ void rt2800_process_rxwi(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2800_process_rxwi); -void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi) +void rt2800_txdone_entry(struct queue_entry *entry, u32 status) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); @@ -609,11 +609,13 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi) u32 word; u16 mcs, real_mcs; int aggr, ampdu; + __le32 *txwi; /* * Obtain the status about this packet. */ txdesc.flags = 0; + txwi = rt2800_drv_get_txwi(entry); rt2x00_desc_read(txwi, 0, &word); mcs = rt2x00_get_field32(word, TXWI_W0_MCS); @@ -897,12 +899,28 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev, } } +static int rt2800_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2800_register_read(led->rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); + rt2800_register_write(led->rt2x00dev, LED_CFG, reg); + + return 0; +} + static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, struct rt2x00_led *led, enum led_type type) { led->rt2x00dev = rt2x00dev; led->type = type; led->led_dev.brightness_set = rt2800_brightness_set; + led->led_dev.blink_set = rt2800_blink_set; led->flags = LED_INITIALIZED; } #endif /* CONFIG_RT2X00_LIB_LEDS */ @@ -910,51 +928,11 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, /* * Configuration handlers. */ -static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev, - const u8 *address, - int wcid) +static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) { struct mac_wcid_entry wcid_entry; - u32 offset; - - offset = MAC_WCID_ENTRY(wcid); - - memset(&wcid_entry, 0xff, sizeof(wcid_entry)); - if (address) - memcpy(wcid_entry.mac, address, ETH_ALEN); - - rt2800_register_multiwrite(rt2x00dev, offset, - &wcid_entry, sizeof(wcid_entry)); -} - -static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid) -{ - u32 offset; - offset = MAC_WCID_ATTR_ENTRY(wcid); - rt2800_register_write(rt2x00dev, offset, 0); -} - -static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev, - int wcid, u32 bssidx) -{ - u32 offset = MAC_WCID_ATTR_ENTRY(wcid); - u32 reg; - - /* - * The BSS Idx numbers is split in a main value of 3 bits, - * and a extended field for adding one additional bit to the value. - */ - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, - (bssidx & 0x8) >> 3); - rt2800_register_write(rt2x00dev, offset, reg); -} - -static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ struct mac_iveiv_entry iveiv_entry; u32 offset; u32 reg; @@ -974,16 +952,14 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, (crypto->cipher & 0x7)); rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, (crypto->cipher & 0x8) >> 3); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->bssidx & 0x7)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, + (crypto->bssidx & 0x8) >> 3); rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); rt2800_register_write(rt2x00dev, offset, reg); } else { - /* Delete the cipher without touching the bssidx */ - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, 0); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, 0); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); - rt2800_register_write(rt2x00dev, offset, reg); + rt2800_register_write(rt2x00dev, offset, 0); } offset = MAC_IVEIV_ENTRY(key->hw_key_idx); @@ -996,6 +972,14 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, iveiv_entry.iv[3] |= key->keyidx << 6; rt2800_register_multiwrite(rt2x00dev, offset, &iveiv_entry, sizeof(iveiv_entry)); + + offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) + memcpy(wcid_entry.mac, crypto->address, ETH_ALEN); + rt2800_register_multiwrite(rt2x00dev, offset, + &wcid_entry, sizeof(wcid_entry)); } int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, @@ -1042,24 +1026,20 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, /* * Update WCID information */ - rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx); - rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx, - crypto->bssidx); - rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key); + rt2800_config_wcid_attr(rt2x00dev, crypto, key); return 0; } EXPORT_SYMBOL_GPL(rt2800_config_shared_key); -static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev) +static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev) { - struct mac_wcid_entry wcid_entry; int idx; - u32 offset; + u32 offset, reg; /* - * Search for the first free WCID entry and return the corresponding - * index. + * Search for the first free pairwise key entry and return the + * corresponding index. * * Make sure the WCID starts _after_ the last possible shared key * entry (>32). @@ -1069,17 +1049,11 @@ static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev) * first 222 entries. */ for (idx = 33; idx <= 222; idx++) { - offset = MAC_WCID_ENTRY(idx); - rt2800_register_multiread(rt2x00dev, offset, &wcid_entry, - sizeof(wcid_entry)); - if (is_broadcast_ether_addr(wcid_entry.mac)) + offset = MAC_WCID_ATTR_ENTRY(idx); + rt2800_register_read(rt2x00dev, offset, ®); + if (!reg) return idx; } - - /* - * Use -1 to indicate that we don't have any more space in the WCID - * table. - */ return -1; } @@ -1089,15 +1063,13 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, { struct hw_key_entry key_entry; u32 offset; + int idx; if (crypto->cmd == SET_KEY) { - /* - * Allow key configuration only for STAs that are - * known by the hw. - */ - if (crypto->wcid < 0) + idx = rt2800_find_pairwise_keyslot(rt2x00dev); + if (idx < 0) return -ENOSPC; - key->hw_key_idx = crypto->wcid; + key->hw_key_idx = idx; memcpy(key_entry.key, crypto->key, sizeof(key_entry.key)); @@ -1114,59 +1086,12 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, /* * Update WCID information */ - rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key); + rt2800_config_wcid_attr(rt2x00dev, crypto, key); return 0; } EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); -int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - int wcid; - struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); - - /* - * Find next free WCID. - */ - wcid = rt2800_find_wcid(rt2x00dev); - - /* - * Store selected wcid even if it is invalid so that we can - * later decide if the STA is uploaded into the hw. - */ - sta_priv->wcid = wcid; - - /* - * No space left in the device, however, we can still communicate - * with the STA -> No error. - */ - if (wcid < 0) - return 0; - - /* - * Clean up WCID attributes and write STA address to the device. - */ - rt2800_delete_wcid_attr(rt2x00dev, wcid); - rt2800_config_wcid(rt2x00dev, sta->addr, wcid); - rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid, - rt2x00lib_get_bssidx(rt2x00dev, vif)); - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_sta_add); - -int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) -{ - /* - * Remove WCID entry, no need to clean the attributes as they will - * get renewed when the WCID is reused. - */ - rt2800_config_wcid(rt2x00dev, NULL, wcid); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_sta_remove); - void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, const unsigned int filter_flags) { @@ -2846,8 +2771,11 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) SHARED_KEY_MODE_ENTRY(i), 0); for (i = 0; i < 256; i++) { - rt2800_config_wcid(rt2x00dev, NULL, i); - rt2800_delete_wcid_attr(rt2x00dev, i); + static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); + + rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0); rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); } @@ -4481,19 +4409,8 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) { - struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; - /* - * Don't allow aggregation for stations the hardware isn't aware - * of because tx status reports for frames to an unknown station - * always contain wcid=255 and thus we can't distinguish between - * multiple stations which leads to unwanted situations when the - * hw reorders frames due to aggregation. - */ - if (sta_priv->wcid < 0) - return 1; - switch (action) { case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h index 7a2511f6785c..69deb3148ae7 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h @@ -152,7 +152,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, struct txentry_desc *txdesc); void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); -void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi); +void rt2800_txdone_entry(struct queue_entry *entry, u32 status); void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); void rt2800_clear_beacon(struct queue_entry *entry); @@ -166,9 +166,6 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); -int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid); void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, const unsigned int filter_flags); void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index da48c8ac27bd..cabf249aa55b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -619,11 +619,11 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, /* * Initialize TX descriptor */ - word = 0; + rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); rt2x00_desc_write(txd, 0, word); - word = 0; + rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); @@ -634,12 +634,12 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); rt2x00_desc_write(txd, 1, word); - word = 0; + rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_SD_PTR1, skbdesc->skb_dma + TXWI_DESC_SIZE); rt2x00_desc_write(txd, 2, word); - word = 0; + rt2x00_desc_read(txd, 3, &word); rt2x00_set_field32(&word, TXD_W3_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W3_QSEL, 2); @@ -760,7 +760,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) } entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry)); + rt2800_txdone_entry(entry, status); if (--max_tx_done == 0) break; @@ -1015,8 +1015,6 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .get_tkip_seq = rt2800_get_tkip_seq, .set_rts_threshold = rt2800_set_rts_threshold, - .sta_add = rt2x00mac_sta_add, - .sta_remove = rt2x00mac_sta_remove, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2800_conf_tx, .get_tsf = rt2800_get_tsf, @@ -1078,8 +1076,6 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .config_erp = rt2800_config_erp, .config_ant = rt2800_config_ant, .config = rt2800_config, - .sta_add = rt2800_sta_add, - .sta_remove = rt2800_sta_remove, }; static const struct data_queue_desc rt2800pci_queue_rx = { @@ -1157,7 +1153,6 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { #endif #ifdef CONFIG_RT2800PCI_RT53XX { PCI_DEVICE(0x1814, 0x5390) }, - { PCI_DEVICE(0x1814, 0x539a) }, { PCI_DEVICE(0x1814, 0x539f) }, #endif { 0, } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index 4b907a53f97c..507559361d87 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -534,8 +534,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) if (!entry || rt2x00queue_empty(queue)) break; - rt2800_txdone_entry(entry, reg, - rt2800usb_get_txwi(entry)); + rt2800_txdone_entry(entry, reg); } } @@ -750,8 +749,6 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .get_tkip_seq = rt2800_get_tkip_seq, .set_rts_threshold = rt2800_set_rts_threshold, - .sta_add = rt2x00mac_sta_add, - .sta_remove = rt2x00mac_sta_remove, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2800_conf_tx, .get_tsf = rt2800_get_tsf, @@ -809,8 +806,6 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .config_erp = rt2800_config_erp, .config_ant = rt2800_config_ant, .config = rt2800_config, - .sta_add = rt2800_sta_add, - .sta_remove = rt2800_sta_remove, }; static const struct data_queue_desc rt2800usb_queue_rx = { diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index cbf8eb334e96..f82bfeb79ebb 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -478,8 +478,6 @@ struct rt2x00lib_crypto { u8 key[16]; u8 tx_mic[8]; u8 rx_mic[8]; - - int wcid; }; /* @@ -513,19 +511,6 @@ struct rt2x00intf_conf { __le32 bssid[2]; }; -/* - * Private structure for storing STA details - * wcid: Wireless Client ID - */ -struct rt2x00_sta { - int wcid; -}; - -static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta) -{ - return (struct rt2x00_sta *)sta->drv_priv; -} - /* * rt2x00lib callback functions. */ @@ -635,11 +620,6 @@ struct rt2x00lib_ops { void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int changed_flags); - int (*sta_add) (struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); - int (*sta_remove) (struct rt2x00_dev *rt2x00dev, - int wcid); }; /* @@ -1245,12 +1225,6 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, } #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -/* - * Utility functions. - */ -u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif); - /* * Interrupt context handlers. */ @@ -1287,10 +1261,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, #else #define rt2x00mac_set_key NULL #endif /* CONFIG_RT2X00_LIB_CRYPTO */ -int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); int rt2x00mac_get_stats(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index e1fb2a8569be..92ff6a72a2bb 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -32,22 +32,6 @@ #include "rt2x00.h" #include "rt2x00lib.h" -/* - * Utility functions. - */ -u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif) -{ - /* - * When in STA mode, bssidx is always 0 otherwise local_address[5] - * contains the bss number, see BSS_ID_MASK comments for details. - */ - if (rt2x00dev->intf_sta_count) - return 0; - return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1); -} -EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx); - /* * Radio control handlers. */ @@ -930,11 +914,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; - /* - * Tell mac80211 about the size of our private STA structure. - */ - rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta); - /* * Allocate tx status FIFO for driver use. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index cef1c878c37e..4ccf23805973 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -494,7 +494,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct rt2x00lib_crypto crypto; static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; - struct rt2x00_sta *sta_priv = NULL; if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; @@ -505,18 +504,24 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, memset(&crypto, 0, sizeof(crypto)); - crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif); + /* + * When in STA mode, bssidx is always 0 otherwise local_address[5] + * contains the bss number, see BSS_ID_MASK comments for details. + */ + if (rt2x00dev->intf_sta_count) + crypto.bssidx = 0; + else + crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1); + crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) return -EOPNOTSUPP; crypto.cmd = cmd; - if (sta) { + if (sta) crypto.address = sta->addr; - sta_priv = sta_to_rt2x00_sta(sta); - crypto.wcid = sta_priv->wcid; - } else + else crypto.address = bcast_addr; if (crypto.cipher == CIPHER_TKIP) @@ -555,39 +560,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, EXPORT_SYMBOL_GPL(rt2x00mac_set_key); #endif /* CONFIG_RT2X00_LIB_CRYPTO */ -int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); - - /* - * If there's no space left in the device table store - * -1 as wcid but tell mac80211 everything went ok. - */ - if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta)) - sta_priv->wcid = -1; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_sta_add); - -int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); - - /* - * If we never sent the STA to the device no need to clean it up. - */ - if (sta_priv->wcid < 0) - return 0; - - return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid); -} -EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); - void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index 5adfb3eab9cd..29edb9fbe6f1 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -310,16 +310,11 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct rt2x00_sta *sta_priv = NULL; - if (tx_info->control.sta) { + if (tx_info->control.sta) txdesc->u.ht.mpdu_density = tx_info->control.sta->ht_cap.ampdu_density; - sta_priv = sta_to_rt2x00_sta(tx_info->control.sta); - txdesc->u.ht.wcid = sta_priv->wcid; - } - txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ /* diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h index 349008d1fb28..f2100f4ddcff 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -288,8 +288,8 @@ enum txentry_desc_flags { * @signal: PLCP signal. * @service: PLCP service. * @msc: MCS. - * @stbc: Use Space Time Block Coding (only available for MCS rates < 8). - * @ba_size: Size of the recepients RX reorder buffer - 1. + * @stbc: STBC. + * @ba_size: BA size. * @rate_mode: Rate mode (See @enum rate_modulation). * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. @@ -321,7 +321,6 @@ struct txentry_desc { u8 ba_size; u8 mpdu_density; enum txop txop; - int wcid; } ht; } u; diff --git a/trunk/drivers/net/wireless/rtlwifi/base.c b/trunk/drivers/net/wireless/rtlwifi/base.c index 098fc557a88d..0b598db38da9 100644 --- a/trunk/drivers/net/wireless/rtlwifi/base.c +++ b/trunk/drivers/net/wireless/rtlwifi/base.c @@ -664,167 +664,6 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) return hw_rate; } -/* mac80211's rate_idx is like this: - * - * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ - * - * B/G rate: - * (rx_status->flag & RX_FLAG_HT) = 0, - * DESC92_RATE1M-->DESC92_RATE54M ==> idx is 0-->11, - * - * N rate: - * (rx_status->flag & RX_FLAG_HT) = 1, - * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 - * - * 5G band:rx_status->band == IEEE80211_BAND_5GHZ - * A rate: - * (rx_status->flag & RX_FLAG_HT) = 0, - * DESC92_RATE6M-->DESC92_RATE54M ==> idx is 0-->7, - * - * N rate: - * (rx_status->flag & RX_FLAG_HT) = 1, - * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 - */ -int rtlwifi_rate_mapping(struct ieee80211_hw *hw, - bool isht, u8 desc_rate, bool first_ampdu) -{ - int rate_idx; - - if (false == isht) { - if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) { - switch (desc_rate) { - case DESC92_RATE1M: - rate_idx = 0; - break; - case DESC92_RATE2M: - rate_idx = 1; - break; - case DESC92_RATE5_5M: - rate_idx = 2; - break; - case DESC92_RATE11M: - rate_idx = 3; - break; - case DESC92_RATE6M: - rate_idx = 4; - break; - case DESC92_RATE9M: - rate_idx = 5; - break; - case DESC92_RATE12M: - rate_idx = 6; - break; - case DESC92_RATE18M: - rate_idx = 7; - break; - case DESC92_RATE24M: - rate_idx = 8; - break; - case DESC92_RATE36M: - rate_idx = 9; - break; - case DESC92_RATE48M: - rate_idx = 10; - break; - case DESC92_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - } else { - switch (desc_rate) { - case DESC92_RATE6M: - rate_idx = 0; - break; - case DESC92_RATE9M: - rate_idx = 1; - break; - case DESC92_RATE12M: - rate_idx = 2; - break; - case DESC92_RATE18M: - rate_idx = 3; - break; - case DESC92_RATE24M: - rate_idx = 4; - break; - case DESC92_RATE36M: - rate_idx = 5; - break; - case DESC92_RATE48M: - rate_idx = 6; - break; - case DESC92_RATE54M: - rate_idx = 7; - break; - default: - rate_idx = 0; - break; - } - } - - } else { - - switch (desc_rate) { - case DESC92_RATEMCS0: - rate_idx = 0; - break; - case DESC92_RATEMCS1: - rate_idx = 1; - break; - case DESC92_RATEMCS2: - rate_idx = 2; - break; - case DESC92_RATEMCS3: - rate_idx = 3; - break; - case DESC92_RATEMCS4: - rate_idx = 4; - break; - case DESC92_RATEMCS5: - rate_idx = 5; - break; - case DESC92_RATEMCS6: - rate_idx = 6; - break; - case DESC92_RATEMCS7: - rate_idx = 7; - break; - case DESC92_RATEMCS8: - rate_idx = 8; - break; - case DESC92_RATEMCS9: - rate_idx = 9; - break; - case DESC92_RATEMCS10: - rate_idx = 10; - break; - case DESC92_RATEMCS11: - rate_idx = 11; - break; - case DESC92_RATEMCS12: - rate_idx = 12; - break; - case DESC92_RATEMCS13: - rate_idx = 13; - break; - case DESC92_RATEMCS14: - rate_idx = 14; - break; - case DESC92_RATEMCS15: - rate_idx = 15; - break; - default: - rate_idx = 0; - break; - } - } - return rate_idx; -} -EXPORT_SYMBOL(rtlwifi_rate_mapping); - void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, diff --git a/trunk/drivers/net/wireless/rtlwifi/base.h b/trunk/drivers/net/wireless/rtlwifi/base.h index 4ae905983d0d..a91f3eee59c8 100644 --- a/trunk/drivers/net/wireless/rtlwifi/base.h +++ b/trunk/drivers/net/wireless/rtlwifi/base.h @@ -140,6 +140,4 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); extern struct attribute_group rtl_attribute_group; -int rtlwifi_rate_mapping(struct ieee80211_hw *hw, - bool isht, u8 desc_rate, bool first_ampdu); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/debug.c b/trunk/drivers/net/wireless/rtlwifi/debug.c index b2f897acb238..5fa73852cb66 100644 --- a/trunk/drivers/net/wireless/rtlwifi/debug.c +++ b/trunk/drivers/net/wireless/rtlwifi/debug.c @@ -28,16 +28,12 @@ #include "wifi.h" -static unsigned int debug = DBG_EMERG; -module_param(debug, uint, 0); -MODULE_PARM_DESC(debug, "Set global debug level for rtlwifi (0,2-5)"); - void rtl_dbgp_flag_init(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 i; - rtlpriv->dbg.global_debuglevel = debug; + rtlpriv->dbg.global_debuglevel = DBG_EMERG; rtlpriv->dbg.global_debugcomponents = COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND | diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 11f43196e61d..35ff7df41a1d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -220,6 +220,41 @@ enum rtl_desc_qsel { QSLT_CMD = 0x13, }; +enum rtl_desc92c_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, + DESC92C_RATEMCS15_SG = 0x1c, + DESC92C_RATEMCS32 = 0x20, +}; + struct phy_sts_cck_8192s_t { u8 adc_pwdb_X[4]; u8 sq_rpt; @@ -232,4 +267,108 @@ struct h2c_cmd_8192c { u8 *p_cmdbuffer; }; +/* NOTE: reference to rtl8192c_rates struct */ +static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, + u8 desc_rate, bool first_ampdu) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int rate_idx = 0; + + if (first_ampdu) { + if (false == isHT) { + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + ("Rate %d is not support, set to " + "1M rate.\n", desc_rate)); + rate_idx = 0; + break; + } + } else { + rate_idx = 11; + } + return rate_idx; + } + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + /* TODO: How to mapping MCS rate? */ + /* NOTE: referenc to __ieee80211_rx */ + default: + rate_idx = 11; + break; + } + return rate_idx; +} + #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 4c34c4c1ae56..373dc78af1dc 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -318,21 +318,21 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 4fb5ae24dee0..230bbe900d8d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -48,6 +48,104 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) return skb->priority; } +static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) +{ + int rate_idx; + + if (first_ampdu) { + if (false == isht) { + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + rate_idx = 11; + } + + return rate_idx; + } + + switch (desc_rate) { + case DESC92C_RATE1M: + rate_idx = 0; + break; + case DESC92C_RATE2M: + rate_idx = 1; + break; + case DESC92C_RATE5_5M: + rate_idx = 2; + break; + case DESC92C_RATE11M: + rate_idx = 3; + break; + case DESC92C_RATE6M: + rate_idx = 4; + break; + case DESC92C_RATE9M: + rate_idx = 5; + break; + case DESC92C_RATE12M: + rate_idx = 6; + break; + case DESC92C_RATE18M: + rate_idx = 7; + break; + case DESC92C_RATE24M: + rate_idx = 8; + break; + case DESC92C_RATE36M: + rate_idx = 9; + break; + case DESC92C_RATE48M: + rate_idx = 10; + break; + case DESC92C_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 11; + break; + } + return rate_idx; +} + static u8 _rtl92c_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -238,8 +336,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && - pdesc->rxmcs <= DESC92_RATEMCS15) + if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 && + pdesc->rxmcs <= DESC92C_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -572,10 +670,12 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, - (bool)GET_RX_DESC_RXHT(pdesc), - (u8)GET_RX_DESC_RXMCS(pdesc), - (bool)GET_RX_DESC_PAGGR(pdesc)); + rx_status->rate_idx = _rtl92ce_rate_mapping((bool) + GET_RX_DESC_RXHT(pdesc), + (u8) + GET_RX_DESC_RXMCS(pdesc), + (bool) + GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { @@ -668,7 +768,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BW(pdesc, 0); SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc->rts_rate <= DESC92_RATE54M) ? + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); @@ -786,7 +886,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, if (firstseg) SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); SET_TX_DESC_SEQ(pdesc, 0); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 81ae64234f80..0f1177137501 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -538,10 +538,10 @@ do { \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (_pdesc->rxmcs == DESC92_RATE1M || \ - _pdesc->rxmcs == DESC92_RATE2M || \ - _pdesc->rxmcs == DESC92_RATE5_5M || \ - _pdesc->rxmcs == DESC92_RATE11M) + (_pdesc->rxmcs == DESC92C_RATE1M || \ + _pdesc->rxmcs == DESC92C_RATE2M || \ + _pdesc->rxmcs == DESC92C_RATE5_5M || \ + _pdesc->rxmcs == DESC92C_RATE11M) struct rx_fwinfo_92c { u8 gain_trsw[4]; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 060a06f4a885..194fc693c1fa 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -892,8 +892,8 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; if (GET_RX_DESC_RX_MCS(pdesc) && - GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && - GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15) + GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 && + GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h index 35529f701fc0..298fdb724aa5 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h @@ -88,10 +88,10 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter); u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ - GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M) + (GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\ + GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M) struct rx_fwinfo_92c { u8 gain_trsw[4]; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 1e851aae58db..17a8e9628512 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tx_agc[RF90_PATH_A] = 0x10101010; tx_agc[RF90_PATH_B] = 0x10101010; } else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) { + TXHIGHPWRLEVEL_LEVEL2) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; } else{ diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 195666a0c854..942f7a3969a7 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -241,20 +241,20 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, - .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; #define USB_VENDER_ID_REALTEK 0x0bda diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index c4161148e0d8..906e7aa55bc3 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -337,10 +337,10 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, - (bool)GET_RX_DESC_RX_HT(pdesc), - (u8)GET_RX_DESC_RX_MCS(pdesc), - (bool)GET_RX_DESC_PAGGR(pdesc)); + rx_status->rate_idx = _rtl92c_rate_mapping(hw, + (bool)GET_RX_DESC_RX_HT(pdesc), + (u8)GET_RX_DESC_RX_MCS(pdesc), + (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); @@ -406,10 +406,11 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) if (GET_RX_DESC_RX_HT(rxdesc)) rx_status->flag |= RX_FLAG_HT; /* Data rate */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, - (bool)GET_RX_DESC_RX_HT(rxdesc), - (u8)GET_RX_DESC_RX_MCS(rxdesc), - (bool)GET_RX_DESC_PAGGR(rxdesc)); + rx_status->rate_idx = _rtl92c_rate_mapping(hw, + (bool)GET_RX_DESC_RX_HT(rxdesc), + (u8)GET_RX_DESC_RX_MCS(rxdesc), + (bool)GET_RX_DESC_PAGGR(rxdesc) + ); /* There is a phy status after this rx descriptor. */ if (GET_RX_DESC_PHY_STATUS(rxdesc)) { p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); @@ -544,7 +545,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BW(txdesc, 0); SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc->rts_rate <= DESC92_RATE54M) ? + ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { @@ -642,7 +643,7 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, } SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ SET_TX_DESC_OWN(pDesc, 1); - SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M); + SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M); _rtl_tx_desc_checksum(pDesc); } @@ -658,7 +659,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); SET_TX_DESC_SEQ(pdesc, 0); SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/def.h index aff7e19714ff..f0f5f9bfbb7b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/def.h @@ -193,6 +193,41 @@ enum rtl_desc_qsel { QSLT_CMD = 0x13, }; +enum rtl_desc92d_rate { + DESC92D_RATE1M = 0x00, + DESC92D_RATE2M = 0x01, + DESC92D_RATE5_5M = 0x02, + DESC92D_RATE11M = 0x03, + + DESC92D_RATE6M = 0x04, + DESC92D_RATE9M = 0x05, + DESC92D_RATE12M = 0x06, + DESC92D_RATE18M = 0x07, + DESC92D_RATE24M = 0x08, + DESC92D_RATE36M = 0x09, + DESC92D_RATE48M = 0x0a, + DESC92D_RATE54M = 0x0b, + + DESC92D_RATEMCS0 = 0x0c, + DESC92D_RATEMCS1 = 0x0d, + DESC92D_RATEMCS2 = 0x0e, + DESC92D_RATEMCS3 = 0x0f, + DESC92D_RATEMCS4 = 0x10, + DESC92D_RATEMCS5 = 0x11, + DESC92D_RATEMCS6 = 0x12, + DESC92D_RATEMCS7 = 0x13, + DESC92D_RATEMCS8 = 0x14, + DESC92D_RATEMCS9 = 0x15, + DESC92D_RATEMCS10 = 0x16, + DESC92D_RATEMCS11 = 0x17, + DESC92D_RATEMCS12 = 0x18, + DESC92D_RATEMCS13 = 0x19, + DESC92D_RATEMCS14 = 0x1a, + DESC92D_RATEMCS15 = 0x1b, + DESC92D_RATEMCS15_SG = 0x1c, + DESC92D_RATEMCS32 = 0x20, +}; + enum channel_plan { CHPL_FCC = 0, CHPL_IC = 1, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index f6419b7ed2f4..351765df517d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -340,21 +340,21 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15, }; static struct pci_device_id rtl92de_pci_ids[] __devinitdata = { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index 3637c0c33525..dc86fcb0b3a3 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -48,6 +48,99 @@ static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) return skb->priority; } +static int _rtl92de_rate_mapping(bool isht, u8 desc_rate) +{ + int rate_idx; + + if (false == isht) { + switch (desc_rate) { + case DESC92D_RATE1M: + rate_idx = 0; + break; + case DESC92D_RATE2M: + rate_idx = 1; + break; + case DESC92D_RATE5_5M: + rate_idx = 2; + break; + case DESC92D_RATE11M: + rate_idx = 3; + break; + case DESC92D_RATE6M: + rate_idx = 4; + break; + case DESC92D_RATE9M: + rate_idx = 5; + break; + case DESC92D_RATE12M: + rate_idx = 6; + break; + case DESC92D_RATE18M: + rate_idx = 7; + break; + case DESC92D_RATE24M: + rate_idx = 8; + break; + case DESC92D_RATE36M: + rate_idx = 9; + break; + case DESC92D_RATE48M: + rate_idx = 10; + break; + case DESC92D_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + return rate_idx; + } else { + switch (desc_rate) { + case DESC92D_RATE1M: + rate_idx = 0; + break; + case DESC92D_RATE2M: + rate_idx = 1; + break; + case DESC92D_RATE5_5M: + rate_idx = 2; + break; + case DESC92D_RATE11M: + rate_idx = 3; + break; + case DESC92D_RATE6M: + rate_idx = 4; + break; + case DESC92D_RATE9M: + rate_idx = 5; + break; + case DESC92D_RATE12M: + rate_idx = 6; + break; + case DESC92D_RATE18M: + rate_idx = 7; + break; + case DESC92D_RATE24M: + rate_idx = 8; + break; + case DESC92D_RATE36M: + rate_idx = 9; + break; + case DESC92D_RATE48M: + rate_idx = 10; + break; + case DESC92D_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 11; + break; + } + return rate_idx; + } +} + static u8 _rtl92d_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -235,8 +328,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, pstats->rx_pwdb_all = pwdb_all; pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && - pdesc->rxmcs <= DESC92_RATEMCS15) + if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 && + pdesc->rxmcs <= DESC92D_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -516,10 +609,10 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, - (bool)GET_RX_DESC_RXHT(pdesc), - (u8)GET_RX_DESC_RXMCS(pdesc), - (bool)GET_RX_DESC_PAGGR(pdesc)); + rx_status->rate_idx = _rtl92de_rate_mapping((bool) + GET_RX_DESC_RXHT(pdesc), + (u8) + GET_RX_DESC_RXMCS(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + @@ -612,14 +705,14 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, } /* 5G have no CCK rate */ if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->hw_rate < DESC92_RATE6M) - ptcb_desc->hw_rate = DESC92_RATE6M; + if (ptcb_desc->hw_rate < DESC92D_RATE6M) + ptcb_desc->hw_rate = DESC92D_RATE6M; SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); if (rtlhal->macphymode == DUALMAC_DUALPHY && - ptcb_desc->hw_rate == DESC92_RATEMCS7) + ptcb_desc->hw_rate == DESC92D_RATEMCS7) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); if (info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -635,13 +728,13 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); /* 5G have no CCK rate */ if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->rts_rate < DESC92_RATE6M) - ptcb_desc->rts_rate = DESC92_RATE6M; + if (ptcb_desc->rts_rate < DESC92D_RATE6M) + ptcb_desc->rts_rate = DESC92D_RATE6M; SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC92_RATE54M) ? + DESC92D_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); if (bw_40) { @@ -751,9 +844,9 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, * The braces are needed no matter what checkpatch says */ if (rtlhal->current_bandtype == BAND_ON_5G) { - SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE6M); + SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M); } else { - SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M); } SET_TX_DESC_SEQ(pdesc, 0); SET_TX_DESC_LINIP(pdesc, 0); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 6c2236868c9a..992d6766e667 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.h @@ -538,10 +538,10 @@ do { \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (_pdesc->rxmcs == DESC92_RATE1M || \ - _pdesc->rxmcs == DESC92_RATE2M || \ - _pdesc->rxmcs == DESC92_RATE5_5M || \ - _pdesc->rxmcs == DESC92_RATE11M) + (_pdesc->rxmcs == DESC92D_RATE1M || \ + _pdesc->rxmcs == DESC92D_RATE2M || \ + _pdesc->rxmcs == DESC92D_RATE5_5M || \ + _pdesc->rxmcs == DESC92D_RATE11M) /* For 92D early mode */ #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 68204ea175dd..69828f2b3fab 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h @@ -33,6 +33,37 @@ #define RX_CMD_QUEUE 1 #define RX_MAX_QUEUE 2 +#define DESC92S_RATE1M 0x00 +#define DESC92S_RATE2M 0x01 +#define DESC92S_RATE5_5M 0x02 +#define DESC92S_RATE11M 0x03 +#define DESC92S_RATE6M 0x04 +#define DESC92S_RATE9M 0x05 +#define DESC92S_RATE12M 0x06 +#define DESC92S_RATE18M 0x07 +#define DESC92S_RATE24M 0x08 +#define DESC92S_RATE36M 0x09 +#define DESC92S_RATE48M 0x0a +#define DESC92S_RATE54M 0x0b +#define DESC92S_RATEMCS0 0x0c +#define DESC92S_RATEMCS1 0x0d +#define DESC92S_RATEMCS2 0x0e +#define DESC92S_RATEMCS3 0x0f +#define DESC92S_RATEMCS4 0x10 +#define DESC92S_RATEMCS5 0x11 +#define DESC92S_RATEMCS6 0x12 +#define DESC92S_RATEMCS7 0x13 +#define DESC92S_RATEMCS8 0x14 +#define DESC92S_RATEMCS9 0x15 +#define DESC92S_RATEMCS10 0x16 +#define DESC92S_RATEMCS11 0x17 +#define DESC92S_RATEMCS12 0x18 +#define DESC92S_RATEMCS13 0x19 +#define DESC92S_RATEMCS14 0x1a +#define DESC92S_RATEMCS15 0x1b +#define DESC92S_RATEMCS15_SG 0x1c +#define DESC92S_RATEMCS32 0x20 + #define SHORT_SLOT_TIME 9 #define NON_SHORT_SLOT_TIME 20 @@ -460,10 +491,10 @@ do { \ SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) #define RX_HAL_IS_CCK_RATE(_pdesc)\ - (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M) + (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) enum rf_optype { RF_OP_BY_SW_3WIRE = 0, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 0055a1c845a2..3876078a63de 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -348,21 +348,21 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { .maps[RTL_IMR_ROK] = IMR_ROK, .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, + .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, }; static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index d9aeae7f8bdb..cffe30851f79 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -51,6 +51,104 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) return skb->priority; } +static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) +{ + int rate_idx = 0; + + if (first_ampdu) { + if (false == isht) { + switch (desc_rate) { + case DESC92S_RATE1M: + rate_idx = 0; + break; + case DESC92S_RATE2M: + rate_idx = 1; + break; + case DESC92S_RATE5_5M: + rate_idx = 2; + break; + case DESC92S_RATE11M: + rate_idx = 3; + break; + case DESC92S_RATE6M: + rate_idx = 4; + break; + case DESC92S_RATE9M: + rate_idx = 5; + break; + case DESC92S_RATE12M: + rate_idx = 6; + break; + case DESC92S_RATE18M: + rate_idx = 7; + break; + case DESC92S_RATE24M: + rate_idx = 8; + break; + case DESC92S_RATE36M: + rate_idx = 9; + break; + case DESC92S_RATE48M: + rate_idx = 10; + break; + case DESC92S_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + rate_idx = 11; + } + + return rate_idx; + } + + switch (desc_rate) { + case DESC92S_RATE1M: + rate_idx = 0; + break; + case DESC92S_RATE2M: + rate_idx = 1; + break; + case DESC92S_RATE5_5M: + rate_idx = 2; + break; + case DESC92S_RATE11M: + rate_idx = 3; + break; + case DESC92S_RATE6M: + rate_idx = 4; + break; + case DESC92S_RATE9M: + rate_idx = 5; + break; + case DESC92S_RATE12M: + rate_idx = 6; + break; + case DESC92S_RATE18M: + rate_idx = 7; + break; + case DESC92S_RATE24M: + rate_idx = 8; + break; + case DESC92S_RATE36M: + rate_idx = 9; + break; + case DESC92S_RATE48M: + rate_idx = 10; + break; + case DESC92S_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 11; + break; + } + return rate_idx; +} + static u8 _rtl92s_query_rxpwrpercentage(char antpower) { if ((antpower <= -100) || (antpower >= 20)) @@ -247,8 +345,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, pstats->recvsignalpower = rx_pwr_all; if (GET_RX_STATUS_DESC_RX_HT(pdesc) && - GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && - GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15) + GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && + GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -556,10 +654,10 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, - (bool)GET_RX_STATUS_DESC_RX_HT(pdesc), - (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), - (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); + rx_status->rate_idx = _rtl92se_rate_mapping((bool) + GET_RX_STATUS_DESC_RX_HT(pdesc), + (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), + (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); @@ -625,14 +723,14 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= - DESC92_RATEMCS0) ? 1 : 0)); + DESC92S_RATEMCS0) ? 1 : 0)); if (rtlhal->version == VERSION_8192S_ACUT) { - if (ptcb_desc->hw_rate == DESC92_RATE1M || - ptcb_desc->hw_rate == DESC92_RATE2M || - ptcb_desc->hw_rate == DESC92_RATE5_5M || - ptcb_desc->hw_rate == DESC92_RATE11M) { - ptcb_desc->hw_rate = DESC92_RATE12M; + if (ptcb_desc->hw_rate == DESC92S_RATE1M || + ptcb_desc->hw_rate == DESC92S_RATE2M || + ptcb_desc->hw_rate == DESC92S_RATE5_5M || + ptcb_desc->hw_rate == DESC92S_RATE11M) { + ptcb_desc->hw_rate = DESC92S_RATE12M; } } @@ -661,7 +759,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC92_RATE54M) ? + DESC92S_RATE54M) ? (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : (ptcb_desc->rts_use_shortgi ? 1 : 0))); diff --git a/trunk/drivers/net/wireless/rtlwifi/wifi.h b/trunk/drivers/net/wireless/rtlwifi/wifi.h index 8a9091968f31..d3c3ffd38984 100644 --- a/trunk/drivers/net/wireless/rtlwifi/wifi.h +++ b/trunk/drivers/net/wireless/rtlwifi/wifi.h @@ -386,41 +386,6 @@ enum rtl_hal_state { _HAL_STATE_START = 1, }; -enum rtl_desc92_rate { - DESC92_RATE1M = 0x00, - DESC92_RATE2M = 0x01, - DESC92_RATE5_5M = 0x02, - DESC92_RATE11M = 0x03, - - DESC92_RATE6M = 0x04, - DESC92_RATE9M = 0x05, - DESC92_RATE12M = 0x06, - DESC92_RATE18M = 0x07, - DESC92_RATE24M = 0x08, - DESC92_RATE36M = 0x09, - DESC92_RATE48M = 0x0a, - DESC92_RATE54M = 0x0b, - - DESC92_RATEMCS0 = 0x0c, - DESC92_RATEMCS1 = 0x0d, - DESC92_RATEMCS2 = 0x0e, - DESC92_RATEMCS3 = 0x0f, - DESC92_RATEMCS4 = 0x10, - DESC92_RATEMCS5 = 0x11, - DESC92_RATEMCS6 = 0x12, - DESC92_RATEMCS7 = 0x13, - DESC92_RATEMCS8 = 0x14, - DESC92_RATEMCS9 = 0x15, - DESC92_RATEMCS10 = 0x16, - DESC92_RATEMCS11 = 0x17, - DESC92_RATEMCS12 = 0x18, - DESC92_RATEMCS13 = 0x19, - DESC92_RATEMCS14 = 0x1a, - DESC92_RATEMCS15 = 0x1b, - DESC92_RATEMCS15_SG = 0x1c, - DESC92_RATEMCS32 = 0x20, -}; - enum rtl_var_map { /*reg map */ SYS_ISO_CTRL = 0, diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index 82f4408e89ad..20e7bc78a7fe 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -2064,6 +2064,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->vif = NULL; + wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl1271_free_ap_keys(wl); memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; @@ -2653,6 +2654,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + /* + * A STA set to GEM cipher requires 2 tx spare blocks. + * Return to default value when GEM cipher key is removed + */ + if (key_type == KEY_GEM) { + if (action == KEY_ADD_OR_REPLACE) + wl->tx_spare_blocks = 2; + else if (action == KEY_REMOVE) + wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + } + addr = sta ? sta->addr : bcast_addr; if (is_zero_ether_addr(addr)) { @@ -4599,6 +4611,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sched_scanning = false; wl->tx_security_seq = 0; wl->tx_security_last_seq_lsb = 0; + wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->role_id = WL12XX_INVALID_ROLE_ID; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->sta_hlid = WL12XX_INVALID_LINK_ID; diff --git a/trunk/drivers/net/wireless/wl12xx/sdio_test.c b/trunk/drivers/net/wireless/wl12xx/sdio_test.c index c3610492852e..f28915392877 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio_test.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio_test.c @@ -193,7 +193,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ret = request_firmware(&fw, WL128X_FW_NAME, wl1271_wl_to_dev(wl)); else - ret = request_firmware(&fw, WL127X_FW_NAME, + ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index 0f1578577b1a..08227e69616b 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -204,9 +204,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 len; u32 total_blocks; int id, ret = -EBUSY, ac; - - /* we use 1 spare block */ - u32 spare_blocks = 1; + u32 spare_blocks = wl->tx_spare_blocks; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -220,6 +218,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, in the firmware */ len = wl12xx_calc_packet_alignment(wl, total_len); + /* in case of a dummy packet, use default amount of spare mem blocks */ + if (unlikely(wl12xx_is_dummy_packet(wl, skb))) + spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + spare_blocks; diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index 7da35c0e411b..6519be4b2c38 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -25,6 +25,7 @@ #ifndef __TX_H__ #define __TX_H__ +#define TX_HW_BLOCK_SPARE_DEFAULT 1 #define TX_HW_BLOCK_SIZE 252 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index 61a7c2163ea2..fb2753c46300 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -425,6 +425,9 @@ struct wl1271 { u32 tx_allocated_blocks; u32 tx_results_count; + /* amount of spare TX blocks to use */ + u32 tx_spare_blocks; + /* Accounting for allocated / available Tx packets in HW */ u32 tx_pkts_freed[NUM_TX_QUEUES]; u32 tx_allocated_pkts[NUM_TX_QUEUES]; diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index f81a93e5b59d..c77e0543e502 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -1246,6 +1246,7 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) { int payload_len = skb->len; struct pn533_frame *out_frame; + struct sk_buff *discarded; u8 tg; nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__, @@ -1259,6 +1260,18 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) return -ENOSYS; } + /* Reserving header space */ + if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) { + nfc_dev_err(&dev->interface->dev, "Error to add header data"); + return -ENOMEM; + } + + /* Reserving tail space, see pn533_tx_frame_finish */ + if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) { + nfc_dev_err(&dev->interface->dev, "Error to add tail data"); + return -ENOMEM; + } + skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); out_frame = (struct pn533_frame *) skb->data; @@ -1523,9 +1536,7 @@ static int pn533_probe(struct usb_interface *interface, | NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK; - dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - PN533_CMD_DATAEXCH_HEAD_LEN, - PN533_FRAME_TAIL_SIZE); + dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols); if (!dev->nfc_dev) goto kill_tasklet; diff --git a/trunk/drivers/ssb/main.c b/trunk/drivers/ssb/main.c index d0cbdb0cf9d5..29c7d4f9d1ae 100644 --- a/trunk/drivers/ssb/main.c +++ b/trunk/drivers/ssb/main.c @@ -1260,34 +1260,16 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) } EXPORT_SYMBOL(ssb_device_disable); -/* Some chipsets need routing known for PCIe and 64-bit DMA */ -static bool ssb_dma_translation_special_bit(struct ssb_device *dev) -{ - u16 chip_id = dev->bus->chip_id; - - if (dev->id.coreid == SSB_DEV_80211) { - return (chip_id == 0x4322 || chip_id == 43221 || - chip_id == 43231 || chip_id == 43222); - } - - return 0; -} - u32 ssb_dma_translation(struct ssb_device *dev) { switch (dev->bus->bustype) { case SSB_BUSTYPE_SSB: return 0; case SSB_BUSTYPE_PCI: - if (pci_is_pcie(dev->bus->host_pci) && - ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) { + if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) return SSB_PCIE_DMA_H32; - } else { - if (ssb_dma_translation_special_bit(dev)) - return SSB_PCIE_DMA_H32; - else - return SSB_PCI_DMA; - } + else + return SSB_PCI_DMA; default: __ssb_dma_not_implemented(dev); } diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index d497a93748a1..06c9081d596d 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -126,6 +126,8 @@ source "drivers/staging/quickstart/Kconfig" source "drivers/staging/sbe-2t3e3/Kconfig" +source "drivers/staging/ath6kl/Kconfig" + source "drivers/staging/keucr/Kconfig" source "drivers/staging/bcm/Kconfig" diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index fe6c6114a668..f3c5e33bb263 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_SOLO6X10) += solo6x10/ obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/ obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/ obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/ +obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/ obj-$(CONFIG_USB_ENESTORAGE) += keucr/ obj-$(CONFIG_BCM_WIMAX) += bcm/ obj-$(CONFIG_FT1000) += ft1000/ diff --git a/trunk/drivers/staging/ath6kl/Kconfig b/trunk/drivers/staging/ath6kl/Kconfig new file mode 100644 index 000000000000..afd6cc16a2b8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/Kconfig @@ -0,0 +1,158 @@ +config ATH6K_LEGACY + tristate "Atheros AR6003 support (non mac80211)" + depends on MMC && WLAN + depends on CFG80211 + select WIRELESS_EXT + select WEXT_PRIV + help + This module adds support for wireless adapters based on Atheros AR6003 chipset running over SDIO. If you choose to build it as a module, it will be called ath6kl. Pls note that AR6002 and AR6001 are not supported by this driver. + +choice + prompt "AR6003 Board Data Configuration" + depends on ATH6K_LEGACY + default AR600x_SD31_XXX + help + Select the appropriate board data template from the list below that matches your AR6003 based reference design. + +config AR600x_SD31_XXX + bool "SD31-xxx" + help + Board Data file for a standard SD31 reference design (File: bdata.SD31.bin) + +config AR600x_WB31_XXX + bool "WB31-xxx" + help + Board Data file for a standard WB31 (BT/WiFi) reference design (File: bdata.WB31.bin) + +config AR600x_SD32_XXX + bool "SD32-xxx" + help + Board Data file for a standard SD32 (5GHz) reference design (File: bdata.SD32.bin) + +config AR600x_CUSTOM_XXX + bool "CUSTOM-xxx" + help + Board Data file for a custom reference design (File: should be named as bdata.CUSTOM.bin) +endchoice + +config ATH6KL_ENABLE_COEXISTENCE + bool "BT Coexistence support" + depends on ATH6K_LEGACY + help + Enables WLAN/BT coexistence support. Select the apprpriate configuration from below. + +choice + prompt "Front-End Antenna Configuration" + depends on ATH6KL_ENABLE_COEXISTENCE + default AR600x_DUAL_ANTENNA + help + Indicates the number of antennas being used by BT and WLAN. Select the appropriate configuration from the list below that matches your AR6003 based reference design. + +config AR600x_DUAL_ANTENNA + bool "Dual Antenna" + help + Dual Antenna Design + +config AR600x_SINGLE_ANTENNA + bool "Single Antenna" + help + Single Antenna Design +endchoice + +choice + prompt "Collocated Bluetooth Type" + depends on ATH6KL_ENABLE_COEXISTENCE + default AR600x_BT_AR3001 + help + Select the appropriate configuration from the list below that matches your AR6003 based reference design. + +config AR600x_BT_QCOM + bool "Qualcomm BTS4020X" + help + Qualcomm BT (3 Wire PTA) + +config AR600x_BT_CSR + bool "CSR BC06" + help + CSR BT (3 Wire PTA) + +config AR600x_BT_AR3001 + bool "Atheros AR3001" + help + Atheros BT (3 Wire PTA) +endchoice + +config ATH6KL_HCI_BRIDGE + bool "HCI over SDIO support" + depends on ATH6K_LEGACY + help + Enables BT over SDIO. Applicable only for combo designs (eg: WB31) + +config ATH6KL_CONFIG_GPIO_BT_RESET + bool "Configure BT Reset GPIO" + depends on ATH6KL_HCI_BRIDGE + help + Configure a WLAN GPIO for use with BT. + +config AR600x_BT_RESET_PIN + int "GPIO" + depends on ATH6KL_CONFIG_GPIO_BT_RESET + default 22 + help + WLAN GPIO to be used for resetting BT + +config ATH6KL_HTC_RAW_INTERFACE + bool "RAW HTC support" + depends on ATH6K_LEGACY + help + Enables raw HTC interface. Allows application to directly talk to the HTC interface via the ioctl interface + +config ATH6KL_VIRTUAL_SCATTER_GATHER + bool "Virtual Scatter-Gather support" + depends on ATH6K_LEGACY + help + Enables virtual scatter gather support for the hardware that does not support it natively. + +config ATH6KL_SKIP_ABI_VERSION_CHECK + bool "Skip ABI version check support" + depends on ATH6K_LEGACY + help + Forces the driver to disable ABI version check. Caution: Incompatilbity between the host driver and target firmware may lead to unknown side effects. + +config ATH6KL_BT_UART_FC_POLARITY + int "UART Flow Control Polarity" + depends on ATH6KL_LEGACY + default 0 + help + Configures the polarity of UART Flow Control. A value of 0 implies active low and is the default setting. Set it to 1 for active high. + +config ATH6KL_DEBUG + bool "Debug support" + depends on ATH6K_LEGACY + help + Enables debug support + +config ATH6KL_ENABLE_HOST_DEBUG + bool "Host Debug support" + depends on ATH6KL_DEBUG + help + Enables debug support in the driver + +config ATH6KL_ENABLE_TARGET_DEBUG_PRINTS + bool "Target Debug support - Enable UART prints" + depends on ATH6KL_DEBUG + help + Enables uart prints + +config AR600x_DEBUG_UART_TX_PIN + int "GPIO" + depends on ATH6KL_ENABLE_TARGET_DEBUG_PRINTS + default 8 + help + WLAN GPIO to be used for Debug UART (Tx) + +config ATH6KL_DISABLE_TARGET_DBGLOGS + bool "Target Debug support - Disable Debug logs" + depends on ATH6KL_DEBUG + help + Enables debug logs diff --git a/trunk/drivers/staging/ath6kl/Makefile b/trunk/drivers/staging/ath6kl/Makefile new file mode 100644 index 000000000000..1d3f2390a172 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/Makefile @@ -0,0 +1,122 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2004-2010 Atheros Communications Inc. +# All rights reserved. +# +# +# +# Permission to use, copy, modify, and/or 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. +# +# +# +# Author(s): ="Atheros" +#------------------------------------------------------------------------------ + +ccflags-y += -I$(obj)/include +ccflags-y += -I$(obj)/include/common +ccflags-y += -I$(obj)/wlan/include +ccflags-y += -I$(obj)/os/linux/include +ccflags-y += -I$(obj)/os +ccflags-y += -I$(obj)/bmi/include +ccflags-y += -I$(obj)/include/common/AR6002/hw4.0 + +ifeq ($(CONFIG_AR600x_DUAL_ANTENNA),y) +ccflags-y += -DAR600x_DUAL_ANTENNA +endif + +ifeq ($(CONFIG_AR600x_SINGLE_ANTENNA),y) +ccflags-y += -DAR600x_SINGLE_ANTENNA +endif + +ifeq ($(CONFIG_AR600x_BT_QCOM),y) +ccflags-y += -DAR600x_BT_QCOM +endif + +ifeq ($(CONFIG_AR600x_BT_CSR),y) +ccflags-y += -DAR600x_BT_CSR +endif + +ifeq ($(CONFIG_AR600x_BT_AR3001),y) +ccflags-y += -DAR600x_BT_AR3001 +endif + +ifeq ($(CONFIG_ATH6KL_HCI_BRIDGE),y) +ccflags-y += -DATH_AR6K_ENABLE_GMBOX +ccflags-y += -DHCI_TRANSPORT_SDIO +ccflags-y += -DSETUPHCI_ENABLED +ccflags-y += -DSETUPBTDEV_ENABLED +ath6kl-y += htc2/AR6000/ar6k_gmbox.o +ath6kl-y += htc2/AR6000/ar6k_gmbox_hciuart.o +ath6kl-y += miscdrv/ar3kconfig.o +ath6kl-y += miscdrv/ar3kps/ar3kpsconfig.o +ath6kl-y += miscdrv/ar3kps/ar3kpsparser.o +endif + +ifeq ($(CONFIG_ATH6KL_CONFIG_GPIO_BT_RESET),y) +ccflags-y += -DATH6KL_CONFIG_GPIO_BT_RESET +endif + +ifeq ($(CONFIG_ATH6KL_HTC_RAW_INTERFACE),y) +ccflags-y += -DHTC_RAW_INTERFACE +endif + +ifeq ($(CONFIG_ATH6KL_ENABLE_HOST_DEBUG),y) +ccflags-y += -DDEBUG +ccflags-y += -DATH_DEBUG_MODULE +endif + +ifeq ($(CONFIG_ATH6KL_ENABLE_TARGET_DEBUG_PRINTS),y) +ccflags-y += -DENABLEUARTPRINT_SET +endif + +ifeq ($(CONFIG_ATH6KL_DISABLE_TARGET_DBGLOGS),y) +ccflags-y += -DATH6KL_DISABLE_TARGET_DBGLOGS +endif + +ifeq ($(CONFIG_ATH6KL_VIRTUAL_SCATTER_GATHER),y) +ccflags-y += -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER +endif + +ifeq ($(CONFIG_ATH6KL_SKIP_ABI_VERSION_CHECK),y) +ccflags-y += -DATH6KL_SKIP_ABI_VERSION_CHECK +endif + +ccflags-y += -DWAPI_ENABLE +ccflags-y += -DCHECKSUM_OFFLOAD + +obj-$(CONFIG_ATH6K_LEGACY) := ath6kl.o +ath6kl-y += htc2/AR6000/ar6k.o +ath6kl-y += htc2/AR6000/ar6k_events.o +ath6kl-y += htc2/htc_send.o +ath6kl-y += htc2/htc_recv.o +ath6kl-y += htc2/htc_services.o +ath6kl-y += htc2/htc.o +ath6kl-y += bmi/src/bmi.o +ath6kl-y += os/linux/cfg80211.o +ath6kl-y += os/linux/ar6000_drv.o +ath6kl-y += os/linux/ar6000_raw_if.o +ath6kl-y += os/linux/ar6000_pm.o +ath6kl-y += os/linux/netbuf.o +ath6kl-y += os/linux/hci_bridge.o +ath6kl-y += miscdrv/common_drv.o +ath6kl-y += miscdrv/credit_dist.o +ath6kl-y += wmi/wmi.o +ath6kl-y += reorder/rcv_aggr.o +ath6kl-y += wlan/src/wlan_node.o +ath6kl-y += wlan/src/wlan_recv_beacon.o +ath6kl-y += wlan/src/wlan_utils.o + +# ATH_HIF_TYPE := sdio +ccflags-y += -I$(obj)/hif/sdio/linux_sdio/include +ccflags-y += -DSDIO +ath6kl-y += hif/sdio/linux_sdio/src/hif.o +ath6kl-y += hif/sdio/linux_sdio/src/hif_scatter.o diff --git a/trunk/drivers/staging/ath6kl/TODO b/trunk/drivers/staging/ath6kl/TODO new file mode 100644 index 000000000000..7be4b46ebb59 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/TODO @@ -0,0 +1,25 @@ +TODO: + +We are working hard on cleaning up the driver. There's sooooooooo much todo +so instead of editing this file please use the wiki: + +http://wireless.kernel.org/en/users/Drivers/ath6kl + +There's a respective TODO page there. Please also subscribe to the wiki page +to get e-mail updates on changes. + +IRC: + +We *really* need to coordinate development for ath6kl as the cleanup +patches will break pretty much any other patches. Please use IRC to +help coordinate better: + +irc.freenode.net +#ath6kl + +Send patches to: + + - Greg Kroah-Hartman + - Luis R. Rodriguez + - Joe Perches + - Naveen Singh diff --git a/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h b/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h new file mode 100644 index 000000000000..8e2577074d65 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef BMI_INTERNAL_H +#define BMI_INTERNAL_H + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME bmi +#include "a_debug.h" +#include "hw/mbox_host_reg.h" +#include "bmi_msg.h" + +#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + + +#define BMI_COMMUNICATION_TIMEOUT 100000 + +/* ------ Global Variable Declarations ------- */ +static bool bmiDone; + +int +bmiBufferSend(struct hif_device *device, + u8 *buffer, + u32 length); + +int +bmiBufferReceive(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout); + +#endif diff --git a/trunk/drivers/staging/ath6kl/bmi/src/bmi.c b/trunk/drivers/staging/ath6kl/bmi/src/bmi.c new file mode 100644 index 000000000000..f1f085eba9c8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/bmi/src/bmi.c @@ -0,0 +1,1010 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// +// Author(s): ="Atheros" +//============================================================================== + + +#ifdef THREAD_X +#include +#endif + +#include "hif.h" +#include "bmi.h" +#include "htc_api.h" +#include "bmi_internal.h" + +#ifdef ATH_DEBUG_MODULE +static struct ath_debug_mask_description bmi_debug_desc[] = { + { ATH_DEBUG_BMI , "BMI Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + "bmi", + "Boot Manager Interface", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + bmi_debug_desc); + +#endif + +/* +Although we had envisioned BMI to run on top of HTC, this is not how the +final implementation ended up. On the Target side, BMI is a part of the BSP +and does not use the HTC protocol nor even DMA -- it is intentionally kept +very simple. +*/ + +static bool pendingEventsFuncCheck = false; +static u32 *pBMICmdCredits; +static u8 *pBMICmdBuf; +#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ + sizeof(u32) /* cmd */ + \ + sizeof(u32) /* addr */ + \ + sizeof(u32))/* length */ +#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ) + +/* APIs visible to the driver */ +void +BMIInit(void) +{ + bmiDone = false; + pendingEventsFuncCheck = false; + + /* + * On some platforms, it's not possible to DMA to a static variable + * in a device driver (e.g. Linux loadable driver module). + * So we need to A_MALLOC space for "command credits" and for commands. + * + * Note: implicitly relies on A_MALLOC to provide a buffer that is + * suitable for DMA (or PIO). This buffer will be passed down the + * bus stack. + */ + if (!pBMICmdCredits) { + pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4); + A_ASSERT(pBMICmdCredits); + } + + if (!pBMICmdBuf) { + pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ); + A_ASSERT(pBMICmdBuf); + } + + A_REGISTER_MODULE_DEBUG_INFO(bmi); +} + +void +BMICleanup(void) +{ + if (pBMICmdCredits) { + kfree(pBMICmdCredits); + pBMICmdCredits = NULL; + } + + if (pBMICmdBuf) { + kfree(pBMICmdBuf); + pBMICmdBuf = NULL; + } +} + +int +BMIDone(struct hif_device *device) +{ + int status; + u32 cid; + + if (bmiDone) { + AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n")); + return 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device)); + bmiDone = true; + cid = BMI_DONE; + + status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + if (pBMICmdCredits) { + kfree(pBMICmdCredits); + pBMICmdCredits = NULL; + } + + if (pBMICmdBuf) { + kfree(pBMICmdBuf); + pBMICmdBuf = NULL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n")); + + return 0; +} + +int +BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info) +{ + int status; + u32 cid; + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device)); + cid = BMI_GET_TARGET_INFO; + + status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver, + sizeof(targ_info->target_ver), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n")); + return A_ERROR; + } + + if (targ_info->target_ver == TARGET_VERSION_SENTINAL) { + /* Determine how many bytes are in the Target's targ_info */ + status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count, + sizeof(targ_info->target_info_byte_count), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n")); + return A_ERROR; + } + + /* + * The Target's targ_info doesn't match the Host's targ_info. + * We need to do some backwards compatibility work to make this OK. + */ + A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info)); + + /* Read the remainder of the targ_info */ + status = bmiBufferReceive(device, + ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count), + sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n", + targ_info->target_info_byte_count)); + return A_ERROR; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", + targ_info->target_ver, targ_info->target_type)); + + return 0; +} + +int +BMIReadMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, rxlen; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length))); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_READ_MEMORY; + + remaining = length; + + while (remaining) + { + rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX; + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen)); + offset += sizeof(length); + + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen); + remaining -= rxlen; address += rxlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n")); + return 0; +} + +int +BMIWriteMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, txlen; + const u32 header = sizeof(cid) + sizeof(address) + sizeof(length); + u8 alignedBuffer[BMI_DATASZ_MAX]; + u8 *src; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_WRITE_MEMORY; + + remaining = length; + while (remaining) + { + src = &buffer[length - remaining]; + if (remaining < (BMI_DATASZ_MAX - header)) { + if (remaining & 3) { + /* align it with 4 bytes */ + remaining = remaining + (4 - (remaining & 3)); + memcpy(alignedBuffer, src, remaining); + src = alignedBuffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + memcpy(&(pBMICmdBuf[offset]), src, txlen); + offset += txlen; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; address += txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n")); + + return 0; +} + +int +BMIExecute(struct hif_device *device, + u32 address, + u32 *param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, *param)); + + cid = BMI_EXECUTE; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param)); + offset += sizeof(*param); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + + memcpy(param, pBMICmdBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param)); + return 0; +} + +int +BMISetAppStart(struct hif_device *device, + u32 address) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_SET_APP_START; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n")); + return 0; +} + +int +BMIReadSOCRegister(struct hif_device *device, + u32 address, + u32 *param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_READ_SOC_REGISTER; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(param, pBMICmdBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param)); + return 0; +} + +int +BMIWriteSOCRegister(struct hif_device *device, + u32 address, + u32 param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, param)); + + cid = BMI_WRITE_SOC_REGISTER; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), ¶m, sizeof(param)); + offset += sizeof(param); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n")); + return 0; +} + +int +BMIrompatchInstall(struct hif_device *device, + u32 ROM_addr, + u32 RAM_addr, + u32 nbytes, + u32 do_activate, + u32 *rompatch_id) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + + sizeof(nbytes) + sizeof(do_activate))); + memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + + sizeof(nbytes) + sizeof(do_activate)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n", + device, ROM_addr, RAM_addr, nbytes, do_activate)); + + cid = BMI_ROMPATCH_INSTALL; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr)); + offset += sizeof(ROM_addr); + memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr)); + offset += sizeof(RAM_addr); + memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes)); + offset += sizeof(nbytes); + memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate)); + offset += sizeof(do_activate); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id)); + return 0; +} + +int +BMIrompatchUninstall(struct hif_device *device, + u32 rompatch_id) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n", + device, rompatch_id)); + + cid = BMI_ROMPATCH_UNINSTALL; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id)); + offset += sizeof(rompatch_id); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id)); + return 0; +} + +static int +_BMIrompatchChangeActivation(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list, + u32 do_activate) +{ + u32 cid; + int status; + u32 offset; + u32 length; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count))); + memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n", + device, rompatch_count)); + + cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count)); + offset += sizeof(rompatch_count); + length = rompatch_count * sizeof(*rompatch_list); + memcpy(&(pBMICmdBuf[offset]), rompatch_list, length); + offset += length; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n")); + + return 0; +} + +int +BMIrompatchActivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list) +{ + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1); +} + +int +BMIrompatchDeactivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list) +{ + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0); +} + +int +BMILZData(struct hif_device *device, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, txlen; + const u32 header = sizeof(cid) + sizeof(length); + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n", + device, length)); + + cid = BMI_LZ_DATA; + + remaining = length; + while (remaining) + { + txlen = (remaining < (BMI_DATASZ_MAX - header)) ? + remaining : (BMI_DATASZ_MAX - header); + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen); + offset += txlen; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n")); + + return 0; +} + +int +BMILZStreamStart(struct hif_device *device, + u32 address) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_LZ_STREAM_START; + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n")); + + return 0; +} + +/* BMI Access routines */ +int +bmiBufferSend(struct hif_device *device, + u8 *buffer, + u32 length) +{ + int status; + u32 timeout; + u32 address; + u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + + while(timeout-- && !(*pBMICmdCredits)) { + /* Read the counter register to get the command credits */ + address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; + /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause + * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to + * make all HIF accesses 4-byte aligned */ + status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4, + HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n")); + return A_ERROR; + } + /* the counter is only 8=bits, ignore anything in the upper 3 bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (*pBMICmdCredits) { + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, + HIF_WR_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n")); + return A_ERROR; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n")); + return A_ERROR; + } + + return status; +} + +int +bmiBufferReceive(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout) +{ + int status; + u32 address; + u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + struct hif_pending_events_info hifPendingEvents; + static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL; + + if (!pendingEventsFuncCheck) { + /* see if the HIF layer implements an alternative function to get pending events + * do this only once! */ + HIFConfigureDevice(device, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + &getPendingEventsFunc, + sizeof(getPendingEventsFunc)); + pendingEventsFuncCheck = true; + } + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + /* + * During normal bootup, small reads may be required. + * Rather than issue an HIF Read and then wait as the Target + * adds successive bytes to the FIFO, we wait here until + * we know that response data is available. + * + * This allows us to cleanly timeout on an unexpected + * Target failure rather than risk problems at the HIF level. In + * particular, this avoids SDIO timeouts and possibly garbage + * data on some host controllers. And on an interconnect + * such as Compact Flash (as well as some SDIO masters) which + * does not provide any indication on data timeout, it avoids + * a potential hang or garbage response. + * + * Synchronization is more difficult for reads larger than the + * size of the MBOX FIFO (128B), because the Target is unable + * to push the 129th byte of data until AFTER the Host posts an + * HIF Read and removes some FIFO data. So for large reads the + * Host proceeds to post an HIF Read BEFORE all the data is + * actually available to read. Fortunately, large BMI reads do + * not occur in practice -- they're supported for debug/development. + * + * So Host/Target BMI synchronization is divided into these cases: + * CASE 1: length < 4 + * Should not happen + * + * CASE 2: 4 <= length <= 128 + * Wait for first 4 bytes to be in FIFO + * If CONSERVATIVE_BMI_READ is enabled, also wait for + * a BMI command credit, which indicates that the ENTIRE + * response is available in the the FIFO + * + * CASE 3: length > 128 + * Wait for the first 4 bytes to be in FIFO + * + * For most uses, a small timeout should be sufficient and we will + * usually see a response quickly; but there may be some unusual + * (debug) cases of BMI_EXECUTE where we want an larger timeout. + * For now, we use an unbounded busy loop while waiting for + * BMI_EXECUTE. + * + * If BMI_EXECUTE ever needs to support longer-latency execution, + * especially in production, this code needs to be enhanced to sleep + * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently + * a function of Host processor speed. + */ + if (length >= 4) { /* NB: Currently, always true */ + /* + * NB: word_available is declared static for esoteric reasons + * having to do with protection on some OSes. + */ + static u32 word_available; + u32 timeout; + + word_available = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !word_available) { + + if (getPendingEventsFunc != NULL) { + status = getPendingEventsFunc(device, + &hifPendingEvents, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n")); + break; + } + + if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) { + word_available = 1; + } + continue; + } + + status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available, + sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n")); + return A_ERROR; + } + /* We did a 4-byte read to the same register; all we really want is one bit */ + word_available &= (1 << ENDPOINT1); + } + + if (!word_available) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n")); + return A_ERROR; + } + } + +#define CONSERVATIVE_BMI_READ 0 +#if CONSERVATIVE_BMI_READ + /* + * This is an extra-conservative CREDIT check. It guarantees + * that ALL data is available in the FIFO before we start to + * read from the interconnect. + * + * This credit check is useless when firmware chooses to + * allow multiple outstanding BMI Command Credits, since the next + * credit will already be present. To restrict the Target to one + * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT. + * + * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set) + * we cannot wait for the next credit because the Target's FIFO + * will not hold the entire response. So we need the Host to + * start to empty the FIFO sooner. (And again, large reads are + * not used in practice; they are for debug/development only.) + * + * For a more conservative Host implementation (which would be + * safer for a Compact Flash interconnect): + * Set CONSERVATIVE_BMI_READ (above) to 1 + * Set HI_OPTION_BMI_CRED_LIMIT and + * reduce BMI_DATASZ_MAX to 32 or 64 + */ + if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */ + u32 timeout; + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !(*pBMICmdCredits) { + /* Read the counter register to get the command credits */ + address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1; + /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing, + * we can read this counter multiple times using a non-incrementing address mode. + * The rationale here is to make all HIF accesses a multiple of 4 bytes */ + status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits), + HIF_RD_SYNC_BYTE_FIX, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n")); + return A_ERROR; + } + /* we did a 4-byte read to the same count register so mask off upper bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (!(*pBMICmdCredits)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n")); + return A_ERROR; + } + } +#endif + + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n")); + return A_ERROR; + } + + return 0; +} + +int +BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length) +{ + int status = A_ERROR; + u32 lastWord = 0; + u32 lastWordOffset = length & ~0x3; + u32 unalignedBytes = length & 0x3; + + status = BMILZStreamStart (device, address); + if (status) { + return A_ERROR; + } + + if (unalignedBytes) { + /* copy the last word into a zero padded buffer */ + memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes); + } + + status = BMILZData(device, buffer, lastWordOffset); + + if (status) { + return A_ERROR; + } + + if (unalignedBytes) { + status = BMILZData(device, (u8 *)&lastWord, 4); + } + + if (!status) { + // + // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. + // + status = BMILZStreamStart (device, 0x00); + if (status) { + return A_ERROR; + } + } + return status; +} + +int +BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length) +{ + return bmiBufferSend(device, buffer, length); +} + +int +BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout) +{ + return bmiBufferReceive(device, buffer, length, want_timeout); +} diff --git a/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h b/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h new file mode 100644 index 000000000000..93a2adceca33 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// common header file for HIF modules designed for SDIO +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef HIF_SDIO_COMMON_H_ +#define HIF_SDIO_COMMON_H_ + + /* SDIO manufacturer ID and Codes */ +#define MANUFACTURER_ID_AR6002_BASE 0x200 +#define MANUFACTURER_ID_AR6003_BASE 0x300 +#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00 +#define FUNCTION_CLASS 0x0 +#define MANUFACTURER_CODE 0x271 /* Atheros */ + + /* Mailbox address in SDIO address space */ +#define HIF_MBOX_BASE_ADDR 0x800 +#define HIF_MBOX_WIDTH 0x800 +#define HIF_MBOX_START_ADDR(mbox) \ + ( HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH) + +#define HIF_MBOX_END_ADDR(mbox) \ + (HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1) + + /* extended MBOX address for larger MBOX writes to MBOX 0*/ +#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024) +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024) + + /* version 1 of the chip has only a 12K extended mbox range */ +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024) + + /* GMBOX addresses */ +#define HIF_GMBOX_BASE_ADDR 0x7000 +#define HIF_GMBOX_WIDTH 0x4000 + + /* for SDIO we recommend a 128-byte block size */ +#define HIF_DEFAULT_IO_BLOCK_SIZE 128 + + /* set extended MBOX window information for SDIO interconnects */ +static INLINE void SetExtendedMboxWindowInfo(u16 Manfid, struct hif_device_mbox_info *pInfo) +{ + switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) { + case MANUFACTURER_ID_AR6002_BASE : + /* MBOX 0 has an extended range */ + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002; + break; + case MANUFACTURER_ID_AR6003_BASE : + /* MBOX 0 has an extended range */ + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1; + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + default: + A_ASSERT(false); + break; + } +} + +/* special CCCR (func 0) registers */ + +#define CCCR_SDIO_IRQ_MODE_REG 0xF0 /* interrupt mode register */ +#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/ + +#endif /*HIF_SDIO_COMMON_H_*/ diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h new file mode 100644 index 000000000000..ed7ad4786f5a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h @@ -0,0 +1,131 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// internal header file for hif layer +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_INTERNAL_H_ +#define _HIF_INTERNAL_H_ + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "hif.h" +#include "../../../common/hif_sdio_common.h" +#include +#define HIF_LINUX_MMC_SCATTER_SUPPORT + +#define BUS_REQUEST_MAX_NUM 64 + +#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 +#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20 +#define FLAGS_CARD_ENAB 0x02 +#define FLAGS_CARD_IRQ_UNMSK 0x04 + +#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE +#define HIF_MBOX0_BLOCK_SIZE 1 +#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE + +typedef struct bus_request { + struct bus_request *next; /* link list of available requests */ + struct bus_request *inusenext; /* link list of in use requests */ + struct semaphore sem_req; + u32 address; /* request data */ + u8 *buffer; + u32 length; + u32 request; + void *context; + int status; + struct hif_scatter_req_priv *pScatterReq; /* this request is a scatter request */ +} BUS_REQUEST; + +struct hif_device { + struct sdio_func *func; + spinlock_t asynclock; + struct task_struct* async_task; /* task to handle async commands */ + struct semaphore sem_async; /* wake up for async task */ + int async_shutdown; /* stop the async task */ + struct completion async_completion; /* thread completion */ + BUS_REQUEST *asyncreq; /* request for async tasklet */ + BUS_REQUEST *taskreq; /* async tasklet data */ + spinlock_t lock; + BUS_REQUEST *s_busRequestFreeQueue; /* free list */ + BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */ + void *claimedContext; + HTC_CALLBACKS htcCallbacks; + u8 *dma_buffer; + struct dl_list ScatterReqHead; /* scatter request list head */ + bool scatter_enabled; /* scatter enabled flag */ + bool is_suspend; + bool is_disabled; + atomic_t irqHandling; + HIF_DEVICE_POWER_CHANGE_TYPE powerConfig; + const struct sdio_device_id *id; +}; + +#define HIF_DMA_BUFFER_SIZE (32 * 1024) +#define CMD53_FIXED_ADDRESS 1 +#define CMD53_INCR_ADDRESS 2 + +BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device); +void hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest); +void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest); + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define MAX_SCATTER_REQUESTS 4 +#define MAX_SCATTER_ENTRIES_PER_REQ 16 +#define MAX_SCATTER_REQ_TRANSFER_SIZE 32*1024 + +struct hif_scatter_req_priv { + struct hif_scatter_req *pHifScatterReq; /* HIF scatter request with allocated entries */ + struct hif_device *device; /* this device */ + BUS_REQUEST *busrequest; /* request associated with request */ + /* scatter list for linux */ + struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ]; +}; + +#define ATH_DEBUG_SCATTER ATH_DEBUG_MAKE_MODULE_MASK(0) + +int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo); +void CleanupHIFScatterResources(struct hif_device *device); +int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest); + +#else // HIF_LINUX_MMC_SCATTER_SUPPORT + +static inline int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo) +{ + return A_ENOTSUP; +} + +static inline int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest) +{ + return A_ENOTSUP; +} + +#define CleanupHIFScatterResources(d) { } + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT + +#endif // _HIF_INTERNAL_H_ + diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c new file mode 100644 index 000000000000..5f5d67720fa4 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c @@ -0,0 +1,1273 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF layer reference implementation for Linux Native MMC stack +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include +#include +#include +#include +#include +#include + +/* by default setup a bounce buffer for the data packets, if the underlying host controller driver + does not use DMA you may be able to skip this step and save the memory allocation and transfer time */ +#define HIF_USE_DMA_BOUNCE_BUFFER 1 +#include "hif_internal.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" +#include "hw/mbox_host_reg.h" + +#if HIF_USE_DMA_BOUNCE_BUFFER +/* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host controllers assume the + * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack). + * virt_addr_valid check fails on stack memory. + */ +#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer))) +#else +#define BUFFER_NEEDS_BOUNCE(buffer) (false) +#endif + +/* ATHENV */ +#if defined(CONFIG_PM) +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) +#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) +#endif /* CONFIG_PM */ +static void delHifDevice(struct hif_device * device); +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte); +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte); + +static int hifEnableFunc(struct hif_device *device, struct sdio_func *func); +static int hifDisableFunc(struct hif_device *device, struct sdio_func *func); +OSDRV_CALLBACKS osdrvCallbacks; + +int reset_sdio_on_unload = 0; +module_param(reset_sdio_on_unload, int, 0644); + +extern u32 nohifscattersupport; + +static struct hif_device *ath6kl_alloc_hifdev(struct sdio_func *func) +{ + struct hif_device *hifdevice; + + hifdevice = kzalloc(sizeof(struct hif_device), GFP_KERNEL); + +#if HIF_USE_DMA_BOUNCE_BUFFER + hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); +#endif + hifdevice->func = func; + hifdevice->powerConfig = HIF_DEVICE_POWER_UP; + sdio_set_drvdata(func, hifdevice); + + return hifdevice; +} + +static struct hif_device *ath6kl_get_hifdev(struct sdio_func *func) +{ + return (struct hif_device *) sdio_get_drvdata(func); +} + +static const struct sdio_device_id ath6kl_hifdev_ids[] = { + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) }, + { /* null */ }, +}; + +MODULE_DEVICE_TABLE(sdio, ath6kl_hifdev_ids); + +static int ath6kl_hifdev_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret; + struct hif_device *device; + int count; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("ath6kl: Function: 0x%X, Vendor ID: 0x%X, " + "Device ID: 0x%X, block size: 0x%X/0x%X\n", + func->num, func->vendor, func->device, + func->max_blksize, func->cur_blksize)); + + ath6kl_alloc_hifdev(func); + device = ath6kl_get_hifdev(func); + + device->id = id; + device->is_disabled = true; + + spin_lock_init(&device->lock); + spin_lock_init(&device->asynclock); + + DL_LIST_INIT(&device->ScatterReqHead); + + /* Try to allow scatter unless globally overridden */ + if (!nohifscattersupport) + device->scatter_enabled = true; + + A_MEMZERO(device->busRequest, sizeof(device->busRequest)); + + for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) { + sema_init(&device->busRequest[count].sem_req, 0); + hifFreeBusRequest(device, &device->busRequest[count]); + } + + sema_init(&device->sem_async, 0); + + ret = hifEnableFunc(device, func); + + return ret; +} + +static void ath6kl_hifdev_remove(struct sdio_func *func) +{ + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + if (device->claimedContext != NULL) + status = osdrvCallbacks. + deviceRemovedHandler(device->claimedContext, device); + + if (device->is_disabled) + device->is_disabled = false; + else + status = hifDisableFunc(device, func); + + CleanupHIFScatterResources(device); + + delHifDevice(device); +} + +#if defined(CONFIG_PM) +static int ath6kl_hifdev_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + + if (device && device->claimedContext && + osdrvCallbacks.deviceSuspendHandler) { + /* set true first for PowerStateChangeNotify(..) */ + device->is_suspend = true; + status = osdrvCallbacks. + deviceSuspendHandler(device->claimedContext); + if (status) + device->is_suspend = false; + } + + CleanupHIFScatterResources(device); + + switch (status) { + case 0: + return 0; + case A_EBUSY: + /* Hack for kernel in order to support deep sleep and wow */ + return -EBUSY; + default: + return -1; + } +} + +static int ath6kl_hifdev_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + if (device && device->claimedContext && + osdrvCallbacks.deviceSuspendHandler) { + status = osdrvCallbacks. + deviceResumeHandler(device->claimedContext); + if (status == 0) + device->is_suspend = false; + } + + return status; +} + +static const struct dev_pm_ops ath6kl_hifdev_pmops = { + .suspend = ath6kl_hifdev_suspend, + .resume = ath6kl_hifdev_resume, +}; +#endif /* CONFIG_PM */ + +static struct sdio_driver ath6kl_hifdev_driver = { + .name = "ath6kl_hifdev", + .id_table = ath6kl_hifdev_ids, + .probe = ath6kl_hifdev_probe, + .remove = ath6kl_hifdev_remove, +#if defined(CONFIG_PM) + .drv = { + .pm = &ath6kl_hifdev_pmops, + }, +#endif +}; + +/* make sure we only unregister when registered. */ +static int registered = 0; + +extern u32 onebitmode; +extern u32 busspeedlow; +extern u32 debughif; + +static void ResetAllCards(void); + +#ifdef DEBUG + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, + "hif", + "(Linux MMC) Host Interconnect Framework", + ATH_DEBUG_MASK_DEFAULTS, + 0, + NULL); + +#endif + + +/* ------ Functions ------ */ +int HIFInit(OSDRV_CALLBACKS *callbacks) +{ + int r; + AR_DEBUG_ASSERT(callbacks != NULL); + + A_REGISTER_MODULE_DEBUG_INFO(hif); + + /* store the callback handlers */ + osdrvCallbacks = *callbacks; + + /* Register with bus driver core */ + registered = 1; + + r = sdio_register_driver(&ath6kl_hifdev_driver); + if (r < 0) + return r; + + return 0; +} + +static int +__HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context) +{ + u8 opcode; + int status = 0; + int ret; + u8 *tbuffer; + bool bounced = false; + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n", + device, buffer, address)); + + do { + if (request & HIF_EXTENDED_IO) { + //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid command type: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_BLOCK_BASIS) { + /* round to whole block length size */ + length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Block mode (BlockLen: %d)\n", + length)); + } else if (request & HIF_BYTE_BASIS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Byte mode (BlockLen: %d)\n", + length)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid data mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + +#if 0 + /* useful for checking register accesses */ + if (length & 0x3) { + A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", + request & HIF_WRITE ? "write":"read", address, length); + } +#endif + + if (request & HIF_WRITE) { + if ((address >= HIF_MBOX_START_ADDR(0)) && + (address <= HIF_MBOX_END_ADDR(3))) + { + + AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH); + + /* + * Mailbox write. Adjust the address so that the last byte + * falls on the EOM address. + */ + address += (HIF_MBOX_WIDTH - length); + } + } + + if (request & HIF_FIXED_ADDRESS) { + opcode = CMD53_FIXED_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address)); + } else if (request & HIF_INCREMENTAL_ADDRESS) { + opcode = CMD53_INCR_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid address mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_WRITE) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer != NULL); + tbuffer = device->dma_buffer; + /* copy the write data to the dma buffer */ + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + memcpy(tbuffer, buffer, length); + bounced = true; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS) { + ret = sdio_writesb(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_toio(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } + } else if (request & HIF_READ) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer != NULL); + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + tbuffer = device->dma_buffer; + bounced = true; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS) { + ret = sdio_readsb(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_fromio(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } +#if HIF_USE_DMA_BOUNCE_BUFFER + if (bounced) { + /* copy the read data from the dma buffer */ + memcpy(buffer, tbuffer, length); + } +#endif + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid direction: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret)); + status = A_ERROR; + } + } while (false); + + return status; +} + +void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest) +{ + unsigned long flags; + BUS_REQUEST *async; + BUS_REQUEST *active; + + spin_lock_irqsave(&device->asynclock, flags); + active = device->asyncreq; + if (active == NULL) { + device->asyncreq = busrequest; + device->asyncreq->inusenext = NULL; + } else { + for (async = device->asyncreq; + async != NULL; + async = async->inusenext) { + active = async; + } + active->inusenext = busrequest; + busrequest->inusenext = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); +} + + +/* queue a read/write request */ +int +HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context) +{ + int status = 0; + BUS_REQUEST *busrequest; + + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address)); + + do { + if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){ + /* serialize all requests through the async thread */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n", + (request & HIF_ASYNCHRONOUS)?"Async":"Synch")); + busrequest = hifAllocateBusRequest(device); + if (busrequest == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n", + request & HIF_READ ? "READ":"WRITE", address, length)); + return A_ERROR; + } + busrequest->address = address; + busrequest->buffer = buffer; + busrequest->length = length; + busrequest->request = request; + busrequest->context = context; + + AddToAsyncList(device, busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest)); + + /* wait for completion */ + up(&device->sem_async); + if (down_interruptible(&busrequest->sem_req) != 0) { + /* interrupted, exit */ + return A_ERROR; + } else { + int status = busrequest->status; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n", + (unsigned long)busrequest, busrequest->status)); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request)); + hifFreeBusRequest(device, busrequest); + return status; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest)); + up(&device->sem_async); + return A_PENDING; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request)); + status = A_EINVAL; + break; + } + } while(0); + + return status; +} +/* thread to serialize all requests, both sync and async */ +static int async_task(void *param) + { + struct hif_device *device; + BUS_REQUEST *request; + int status; + unsigned long flags; + + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n")); + set_current_state(TASK_INTERRUPTIBLE); + while(!device->async_shutdown) { + /* wait for work */ + if (down_interruptible(&device->sem_async) != 0) { + /* interrupted, exit */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n")); + break; + } + if (device->async_shutdown) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n")); + break; + } + /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */ + sdio_claim_host(device->func); + spin_lock_irqsave(&device->asynclock, flags); + /* pull the request to work on */ + while (device->asyncreq != NULL) { + request = device->asyncreq; + if (request->inusenext != NULL) { + device->asyncreq = request->inusenext; + } else { + device->asyncreq = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request)); + + if (request->pScatterReq != NULL) { + A_ASSERT(device->scatter_enabled); + /* this is a queued scatter request, pass the request to scatter routine which + * executes it synchronously, note, no need to free the request since scatter requests + * are maintained on a separate list */ + status = DoHifReadWriteScatter(device,request); + } else { + /* call HIFReadWrite in sync mode to do the work */ + status = __HIFReadWrite(device, request->address, request->buffer, + request->length, request->request & ~HIF_SYNCHRONOUS, NULL); + if (request->request & HIF_ASYNCHRONOUS) { + void *context = request->context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request)); + hifFreeBusRequest(device, request); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request)); + device->htcCallbacks.rwCompletionHandler(context, status); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request)); + request->status = status; + up(&request->sem_req); + } + } + spin_lock_irqsave(&device->asynclock, flags); + } + spin_unlock_irqrestore(&device->asynclock, flags); + sdio_release_host(device->func); + } + + complete_and_exit(&device->async_completion, 0); + return 0; +} + +static s32 IssueSDCommand(struct hif_device *device, u32 opcode, u32 arg, u32 flags, u32 *resp) +{ + struct mmc_command cmd; + s32 err; + struct mmc_host *host; + struct sdio_func *func; + + func = device->func; + host = func->card->host; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = opcode; + cmd.arg = arg; + cmd.flags = flags; + err = mmc_wait_for_cmd(host, &cmd, 3); + + if ((!err) && (resp)) { + *resp = cmd.resp[0]; + } + + return err; +} + +int ReinitSDIO(struct hif_device *device) +{ + s32 err; + struct mmc_host *host; + struct mmc_card *card; + struct sdio_func *func; + u8 cmd52_resp; + u32 clock; + + func = device->func; + card = func->card; + host = card->host; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n")); + sdio_claim_host(func); + + do { + if (!device->is_suspend) { + u32 resp; + u16 rca; + u32 i; + int bit = fls(host->ocr_avail) - 1; + /* emulate the mmc_power_up(...) */ + host->ios.vdd = bit; + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.power_mode = MMC_POWER_UP; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + host->ops->set_ios(host, &host->ios); + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + msleep(2); + + host->ios.clock = host->f_min; + host->ios.power_mode = MMC_POWER_ON; + host->ops->set_ios(host, &host->ios); + + /* + * This delay must be at least 74 clock sizes, or 1 ms, or the + * time required to reach a stable voltage. + */ + msleep(2); + + /* Issue CMD0. Goto idle state */ + host->ios.chip_select = MMC_CS_HIGH; + host->ops->set_ios(host, &host->ios); + msleep(1); + err = IssueSDCommand(device, MMC_GO_IDLE_STATE, 0, (MMC_RSP_NONE | MMC_CMD_BC), NULL); + host->ios.chip_select = MMC_CS_DONTCARE; + host->ops->set_ios(host, &host->ios); + msleep(1); + host->use_spi_crc = 0; + + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD0 failed : %d \n",err)); + break; + } + + if (!host->ocr) { + /* Issue CMD5, arg = 0 */ + err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); + break; + } + host->ocr = resp; + } + + /* Issue CMD5, arg = ocr. Wait till card is ready */ + for (i=0;i<100;i++) { + err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); + break; + } + if (resp & MMC_CARD_BUSY) { + break; + } + msleep(10); + } + + if ((i == 100) || (err)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: card in not ready : %d %d \n",i,err)); + break; + } + + /* Issue CMD3, get RCA */ + err = IssueSDCommand(device, SD_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6 | MMC_CMD_BCR, &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD3 failed : %d \n",err)); + break; + } + rca = resp >> 16; + host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; + host->ops->set_ios(host, &host->ios); + + /* Issue CMD7, select card */ + err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R1 | MMC_CMD_AC, NULL); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD7 failed : %d \n",err)); + break; + } + } + + /* Enable high speed */ + if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n")); + err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err)); + card->state &= ~MMC_STATE_HIGHSPEED; + /* no need to break */ + } else { + err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS)); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err)); + break; + } + mmc_card_set_highspeed(card); + host->ios.timing = MMC_TIMING_SD_HS; + host->ops->set_ios(host, &host->ios); + } + } + + /* Set clock */ + if (mmc_card_highspeed(card)) { + clock = 50000000; + } else { + clock = card->cis.max_dtr; + } + + if (clock > host->f_max) { + clock = host->f_max; + } + host->ios.clock = clock; + host->ops->set_ios(host, &host->ios); + + + if (card->host->caps & MMC_CAP_4_BIT_DATA) { + /* CMD52: Set bus width & disable card detect resistor */ + err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err)); + break; + } + host->ios.bus_width = MMC_BUS_WIDTH_4; + host->ops->set_ios(host, &host->ios); + } + } while (0); + + sdio_release_host(func); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n")); + + return (err) ? A_ERROR : 0; +} + +int +PowerStateChangeNotify(struct hif_device *device, HIF_DEVICE_POWER_CHANGE_TYPE config) +{ + int status = 0; +#if defined(CONFIG_PM) + struct sdio_func *func = device->func; + int old_reset_val; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config)); + switch (config) { + case HIF_DEVICE_POWER_DOWN: + case HIF_DEVICE_POWER_CUT: + old_reset_val = reset_sdio_on_unload; + reset_sdio_on_unload = 1; + status = hifDisableFunc(device, func); + reset_sdio_on_unload = old_reset_val; + if (!device->is_suspend) { + struct mmc_host *host = func->card->host; + host->ios.clock = 0; + host->ios.vdd = 0; + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.power_mode = MMC_POWER_OFF; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + host->ops->set_ios(host, &host->ios); + } + break; + case HIF_DEVICE_POWER_UP: + if (device->powerConfig == HIF_DEVICE_POWER_CUT) { + status = ReinitSDIO(device); + } + if (status == 0) { + status = hifEnableFunc(device, func); + } + break; + } + device->powerConfig = config; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n")); +#endif + return status; +} + +int +HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u32 configLen) +{ + u32 count; + int status = 0; + + switch(opcode) { + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + ((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; + ((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; + ((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; + ((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; + break; + + case HIF_DEVICE_GET_MBOX_ADDR: + for (count = 0; count < 4; count ++) { + ((u32 *)config)[count] = HIF_MBOX_START_ADDR(count); + } + + if (configLen >= sizeof(struct hif_device_mbox_info)) { + SetExtendedMboxWindowInfo((u16)device->func->device, + (struct hif_device_mbox_info *)config); + } + + break; + case HIF_DEVICE_GET_IRQ_PROC_MODE: + *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; + break; + case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: + if (!device->scatter_enabled) { + return A_ENOTSUP; + } + status = SetupHIFScatterSupport(device, (struct hif_device_scatter_support_info *)config); + if (status) { + device->scatter_enabled = false; + } + break; + case HIF_DEVICE_GET_OS_DEVICE: + /* pass back a pointer to the SDIO function's "dev" struct */ + ((struct hif_device_os_device_info *)config)->pOSDevice = &device->func->dev; + break; + case HIF_DEVICE_POWER_STATE_CHANGE: + status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: Unsupported configuration opcode: %d\n", opcode)); + status = A_ERROR; + } + + return status; +} + +void +HIFShutDownDevice(struct hif_device *device) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); + if (device != NULL) { + AR_DEBUG_ASSERT(device->func != NULL); + } else { + /* since we are unloading the driver anyways, reset all cards in case the SDIO card + * is externally powered and we are unloading the SDIO stack. This avoids the problem when + * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already + * enumerated */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n")); + ResetAllCards(); + + /* Unregister with bus driver core */ + if (registered) { + registered = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Unregistering with the bus driver\n")); + sdio_unregister_driver(&ath6kl_hifdev_driver); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Unregistered\n")); + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n")); +} + +static void +hifIRQHandler(struct sdio_func *func) +{ + int status; + struct hif_device *device; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n")); + + device = ath6kl_get_hifdev(func); + atomic_set(&device->irqHandling, 1); + /* release the host during ints so we can pick it back up when we process cmds */ + sdio_release_host(device->func); + status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); + sdio_claim_host(device->func); + atomic_set(&device->irqHandling, 0); + AR_DEBUG_ASSERT(status == 0 || status == A_ECANCELED); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n")); +} + +/* handle HTC startup via thread*/ +static int startup_task(void *param) +{ + struct hif_device *device; + + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); + /* start up inform DRV layer */ + if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + return 0; +} + +#if defined(CONFIG_PM) +static int enable_task(void *param) +{ + struct hif_device *device; + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n")); + + /* start up inform DRV layer */ + if (device && + device->claimedContext && + osdrvCallbacks.devicePowerChangeHandler && + osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + + return 0; +} +#endif + +void +HIFAckInterrupt(struct hif_device *device) +{ + AR_DEBUG_ASSERT(device != NULL); + + /* Acknowledge our function IRQ */ +} + +void +HIFUnMaskInterrupt(struct hif_device *device) +{ + int ret; + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n")); + + /* Register the IRQ Handler */ + sdio_claim_host(device->func); + ret = sdio_claim_irq(device->func, hifIRQHandler); + sdio_release_host(device->func); + AR_DEBUG_ASSERT(ret == 0); +} + +void HIFMaskInterrupt(struct hif_device *device) +{ + int ret; + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n")); + + /* Mask our function IRQ */ + sdio_claim_host(device->func); + while (atomic_read(&device->irqHandling)) { + sdio_release_host(device->func); + schedule_timeout(HZ/10); + sdio_claim_host(device->func); + } + ret = sdio_release_irq(device->func); + sdio_release_host(device->func); + AR_DEBUG_ASSERT(ret == 0); +} + +BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device) +{ + BUS_REQUEST *busrequest; + unsigned long flag; + + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + /* Remove first in list */ + if((busrequest = device->s_busRequestFreeQueue) != NULL) + { + device->s_busRequestFreeQueue = busrequest->next; + } + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest)); + return busrequest; +} + +void +hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest) +{ + unsigned long flag; + + AR_DEBUG_ASSERT(busrequest != NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest)); + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + + /* Insert first in list */ + busrequest->next = device->s_busRequestFreeQueue; + busrequest->inusenext = NULL; + device->s_busRequestFreeQueue = busrequest; + + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); +} + +static int hifDisableFunc(struct hif_device *device, struct sdio_func *func) +{ + int ret; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n")); + device = ath6kl_get_hifdev(func); + if (!IS_ERR(device->async_task)) { + init_completion(&device->async_completion); + device->async_shutdown = 1; + up(&device->sem_async); + wait_for_completion(&device->async_completion); + device->async_task = NULL; + } + /* Disable the card */ + sdio_claim_host(device->func); + ret = sdio_disable_func(device->func); + if (ret) { + status = A_ERROR; + } + + if (reset_sdio_on_unload) { + /* reset the SDIO interface. This is useful in automated testing where the card + * does not need to be removed at the end of the test. It is expected that the user will + * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n")); + + /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access + * to undefined registers in the range of: 0xF0-0xFF */ + + ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)); + if (ret) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret)); + } + } + + sdio_release_host(device->func); + + if (status == 0) { + device->is_disabled = true; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n")); + + return status; +} + +static int hifEnableFunc(struct hif_device *device, struct sdio_func *func) +{ + struct task_struct* pTask; + const char *taskName = NULL; + int (*taskFunc)(void *) = NULL; + int ret = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n")); + device = ath6kl_get_hifdev(func); + + if (device->is_disabled) { + /* enable the SDIO function */ + sdio_claim_host(func); + + if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) { + /* enable 4-bit ASYNC interrupt on AR6003 or later devices */ + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret)); + sdio_release_host(func); + return ret; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n")); + } + /* give us some time to enable, in ms */ + func->enable_timeout = 100; + ret = sdio_enable_func(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n", + __FUNCTION__, ret)); + sdio_release_host(func); + return ret; + } + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); + sdio_release_host(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n", + __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret)); + return ret; + } + device->is_disabled = false; + /* create async I/O thread */ + if (!device->async_task) { + device->async_shutdown = 0; + device->async_task = kthread_create(async_task, + (void *)device, + "AR6K Async"); + if (IS_ERR(device->async_task)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__)); + return -ENOMEM; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); + wake_up_process(device->async_task ); + } + } + + if (!device->claimedContext) { + taskFunc = startup_task; + taskName = "AR6K startup"; + ret = 0; +#if defined(CONFIG_PM) + } else { + taskFunc = enable_task; + taskName = "AR6K enable"; + ret = -ENOMEM; +#endif /* CONFIG_PM */ + } + /* create resume thread */ + pTask = kthread_create(taskFunc, (void *)device, taskName); + if (IS_ERR(pTask)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__)); + return -ENOMEM; + } + wake_up_process(pTask); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n")); + + /* task will call the enable func, indicate pending */ + return ret; +} + +/* + * This should be moved to AR6K HTC layer. + */ +int hifWaitForPendingRecv(struct hif_device *device) +{ + s32 cnt = 10; + u8 host_int_status; + int status = 0; + + do { + while (atomic_read(&device->irqHandling)) { + /* wait until irq handler finished all the jobs */ + schedule_timeout(HZ/10); + } + /* check if there is any pending irq due to force done */ + host_int_status = 0; + status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS, + (u8 *)&host_int_status, sizeof(host_int_status), + HIF_RD_SYNC_BYTE_INC, NULL); + host_int_status = !status ? (host_int_status & (1 << 0)) : 0; + if (host_int_status) { + schedule(); /* schedule for next dsrHandler */ + } + } while (host_int_status && --cnt > 0); + + if (host_int_status && cnt == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__)); + } + + return 0; +} + +static void +delHifDevice(struct hif_device * device) +{ + AR_DEBUG_ASSERT(device!= NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device)); + kfree(device->dma_buffer); + kfree(device); +} + +static void ResetAllCards(void) +{ +} + +void HIFClaimDevice(struct hif_device *device, void *context) +{ + device->claimedContext = context; +} + +void HIFReleaseDevice(struct hif_device *device) +{ + device->claimedContext = NULL; +} + +int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks) +{ + if (device->htcCallbacks.context != NULL) { + /* already in use! */ + return A_ERROR; + } + device->htcCallbacks = *callbacks; + return 0; +} + +void HIFDetachHTC(struct hif_device *device) +{ + A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks)); +} + +#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((raw) & 1) << 27) | \ + (1 << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + (1 << 8) | \ + ((writedata) & 0xFF) + +#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \ + SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00) +#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \ + SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value) + +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + return mmc_wait_for_cmd(card->host, &ioCmd, 0); +} + +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + s32 err; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_READ_ARG(arg,0,address); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &ioCmd, 0); + + if ((!err) && (byte)) { + *byte = ioCmd.resp[0] & 0xFF; + } + + return err; +} diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c new file mode 100644 index 000000000000..7516d913dab3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c @@ -0,0 +1,393 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF scatter implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include +#include +#include +#include +#include +#include +#include "hif_internal.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define _CMD53_ARG_READ 0 +#define _CMD53_ARG_WRITE 1 +#define _CMD53_ARG_BLOCK_BASIS 1 +#define _CMD53_ARG_FIXED_ADDRESS 0 +#define _CMD53_ARG_INCR_ADDRESS 1 + +#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((mode) & 1) << 27) | \ + (((opcode) & 1) << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + ((bytes_blocks) & 0x1FF) + +static void FreeScatterReq(struct hif_device *device, struct hif_scatter_req *pReq) +{ + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + DL_ListInsertTail(&device->ScatterReqHead, &pReq->ListLink); + + spin_unlock_irqrestore(&device->lock, flag); + +} + +static struct hif_scatter_req *AllocScatterReq(struct hif_device *device) +{ + struct dl_list *pItem; + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + pItem = DL_ListRemoveItemFromHead(&device->ScatterReqHead); + + spin_unlock_irqrestore(&device->lock, flag); + + if (pItem != NULL) { + return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink); + } + + return NULL; +} + + /* called by async task to perform the operation synchronously using direct MMC APIs */ +int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest) +{ + int i; + u8 rw; + u8 opcode; + struct mmc_request mmcreq; + struct mmc_command cmd; + struct mmc_data data; + struct hif_scatter_req_priv *pReqPriv; + struct hif_scatter_req *pReq; + int status = 0; + struct scatterlist *pSg; + + pReqPriv = busrequest->pScatterReq; + + A_ASSERT(pReqPriv != NULL); + + pReq = pReqPriv->pHifScatterReq; + + memset(&mmcreq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + data.blksz = HIF_MBOX_BLOCK_SIZE; + data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE; + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks, + pReq->TotalLength,pReq->ValidScatterEntries)); + + if (pReq->Request & HIF_WRITE) { + rw = _CMD53_ARG_WRITE; + data.flags = MMC_DATA_WRITE; + } else { + rw = _CMD53_ARG_READ; + data.flags = MMC_DATA_READ; + } + + if (pReq->Request & HIF_FIXED_ADDRESS) { + opcode = _CMD53_ARG_FIXED_ADDRESS; + } else { + opcode = _CMD53_ARG_INCR_ADDRESS; + } + + /* fill SG entries */ + pSg = pReqPriv->sgentries; + sg_init_table(pSg, pReq->ValidScatterEntries); + + /* assemble SG list */ + for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) { + /* setup each sg entry */ + if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) { + /* note some scatter engines can handle unaligned buffers, print this + * as informational only */ + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, + ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n", + pReq->Request & HIF_WRITE ? "WRITE":"READ", + (unsigned long)pReq->ScatterList[i].pBuffer)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n", + i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length)); + + sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length); + } + /* set scatter-gather table for request */ + data.sg = pReqPriv->sgentries; + data.sg_len = pReq->ValidScatterEntries; + /* set command argument */ + SDIO_SET_CMD53_ARG(cmd.arg, + rw, + device->func->num, + _CMD53_ARG_BLOCK_BASIS, + opcode, + pReq->Address, + data.blocks); + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmcreq.cmd = &cmd; + mmcreq.data = &data; + + mmc_set_data_timeout(&data, device->func->card); + /* synchronous call to process request */ + mmc_wait_for_req(device->func->card->host, &mmcreq); + + if (cmd.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error)); + } + + if (data.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error)); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks)); + } + + /* set completion status, fail or success */ + pReq->CompletionStatus = status; + + if (pReq->Request & HIF_ASYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status)); + /* complete the request */ + A_ASSERT(pReq->CompletionRoutine != NULL); + pReq->CompletionRoutine(pReq); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status)); + /* signal wait */ + up(&busrequest->sem_req); + } + + return status; +} + + /* callback to issue a read-write scatter request */ +static int HifReadWriteScatter(struct hif_device *device, struct hif_scatter_req *pReq) +{ + int status = A_EINVAL; + u32 request = pReq->Request; + struct hif_scatter_req_priv *pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0]; + + do { + + A_ASSERT(pReqPriv != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: total len: %d Scatter Entries: %d\n", + pReq->TotalLength, pReq->ValidScatterEntries)); + + if (!(request & HIF_EXTENDED_IO)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid command type: 0x%08x\n", request)); + break; + } + + if (!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid execution mode: 0x%08x\n", request)); + break; + } + + if (!(request & HIF_BLOCK_BASIS)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid data mode: 0x%08x\n", request)); + break; + } + + if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid length: %d \n", pReq->TotalLength)); + break; + } + + if (pReq->TotalLength == 0) { + A_ASSERT(false); + break; + } + + /* add bus request to the async list for the async I/O thread to process */ + AddToAsyncList(device, pReqPriv->busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued sync req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* signal thread and wait */ + up(&device->sem_async); + if (down_interruptible(&pReqPriv->busrequest->sem_req) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF-SCATTER: interrupted! \n")); + /* interrupted, exit */ + status = A_ERROR; + break; + } else { + status = pReq->CompletionStatus; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* wake thread, it will process and then take care of the async callback */ + up(&device->sem_async); + status = 0; + } + + } while (false); + + if (status && (request & HIF_ASYNCHRONOUS)) { + pReq->CompletionStatus = status; + pReq->CompletionRoutine(pReq); + status = 0; + } + + return status; +} + + /* setup of HIF scatter resources */ +int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo) +{ + int status = A_ERROR; + int i; + struct hif_scatter_req_priv *pReqPriv; + BUS_REQUEST *busrequest; + + do { + + /* check if host supports scatter requests and it meets our requirements */ + if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", + device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ)); + status = A_ENOTSUP; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n", + MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ)); + + for (i = 0; i < MAX_SCATTER_REQUESTS; i++) { + /* allocate the private request blob */ + pReqPriv = (struct hif_scatter_req_priv *)A_MALLOC(sizeof(struct hif_scatter_req_priv)); + if (NULL == pReqPriv) { + break; + } + A_MEMZERO(pReqPriv, sizeof(struct hif_scatter_req_priv)); + /* save the device instance*/ + pReqPriv->device = device; + /* allocate the scatter request */ + pReqPriv->pHifScatterReq = (struct hif_scatter_req *)A_MALLOC(sizeof(struct hif_scatter_req) + + (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item))); + + if (NULL == pReqPriv->pHifScatterReq) { + kfree(pReqPriv); + break; + } + /* just zero the main part of the scatter request */ + A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(struct hif_scatter_req)); + /* back pointer to the private struct */ + pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv; + /* allocate a bus request for this scatter request */ + busrequest = hifAllocateBusRequest(device); + if (NULL == busrequest) { + kfree(pReqPriv->pHifScatterReq); + kfree(pReqPriv); + break; + } + /* assign the scatter request to this bus request */ + busrequest->pScatterReq = pReqPriv; + /* point back to the request */ + pReqPriv->busrequest = busrequest; + /* add it to the scatter pool */ + FreeScatterReq(device,pReqPriv->pHifScatterReq); + } + + if (i != MAX_SCATTER_REQUESTS) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n")); + break; + } + + /* set scatter function pointers */ + pInfo->pAllocateReqFunc = AllocScatterReq; + pInfo->pFreeReqFunc = FreeScatterReq; + pInfo->pReadWriteScatterFunc = HifReadWriteScatter; + pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ; + pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE; + + status = 0; + + } while (false); + + if (status) { + CleanupHIFScatterResources(device); + } + + return status; +} + + /* clean up scatter support */ +void CleanupHIFScatterResources(struct hif_device *device) +{ + struct hif_scatter_req_priv *pReqPriv; + struct hif_scatter_req *pReq; + + /* empty the free list */ + + while (1) { + + pReq = AllocScatterReq(device); + + if (NULL == pReq) { + break; + } + + pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0]; + A_ASSERT(pReqPriv != NULL); + + if (pReqPriv->busrequest != NULL) { + pReqPriv->busrequest->pScatterReq = NULL; + /* free bus request */ + hifFreeBusRequest(device, pReqPriv->busrequest); + pReqPriv->busrequest = NULL; + } + + if (pReqPriv->pHifScatterReq != NULL) { + kfree(pReqPriv->pHifScatterReq); + pReqPriv->pHifScatterReq = NULL; + } + + kfree(pReqPriv); + } +} + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c new file mode 100644 index 000000000000..f8607bc08929 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c @@ -0,0 +1,1479 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K device layer that handles register level I/O +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "hw/mbox_host_reg.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" + +#define MAILBOX_FOR_BLOCK_SIZE 1 + +int DevEnableInterrupts(struct ar6k_device *pDev); +int DevDisableInterrupts(struct ar6k_device *pDev); + +static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev); + +void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket) +{ + LOCK_AR6K(pDev); + HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket); + UNLOCK_AR6K(pDev); +} + +struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev) +{ + struct htc_packet *pPacket; + + LOCK_AR6K(pDev); + pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList); + UNLOCK_AR6K(pDev); + + return pPacket; +} + +void DevCleanup(struct ar6k_device *pDev) +{ + DevCleanupGMbox(pDev); + + if (pDev->HifAttached) { + HIFDetachHTC(pDev->HIFDevice); + pDev->HifAttached = false; + } + + DevCleanupVirtualScatterSupport(pDev); + + if (A_IS_MUTEX_VALID(&pDev->Lock)) { + A_MUTEX_DELETE(&pDev->Lock); + } +} + +int DevSetup(struct ar6k_device *pDev) +{ + u32 blocksizes[AR6K_MAILBOXES]; + int status = 0; + int i; + HTC_CALLBACKS htcCallbacks; + + do { + + DL_LIST_INIT(&pDev->ScatterReqHead); + /* initialize our free list of IO packets */ + INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList); + A_MUTEX_INIT(&pDev->Lock); + + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); + /* the device layer handles these */ + htcCallbacks.rwCompletionHandler = DevRWCompletionHandler; + htcCallbacks.dsrHandler = DevDsrHandler; + htcCallbacks.context = pDev; + + status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks); + + if (status) { + break; + } + + pDev->HifAttached = true; + + /* get the addresses for all 4 mailboxes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, + &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo)); + + if (status) { + A_ASSERT(false); + break; + } + + /* carve up register I/O packets (these are for ASYNC register I/O ) */ + for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) { + struct htc_packet *pIOPacket; + pIOPacket = &pDev->RegIOBuffers[i].HtcPacket; + SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket, + pDev, + pDev->RegIOBuffers[i].Buffer, + AR6K_REG_IO_BUFFER_SIZE, + 0); /* don't care */ + AR6KFreeIOPacket(pDev,pIOPacket); + } + + /* get the block sizes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + + if (status) { + A_ASSERT(false); + break; + } + + /* note: we actually get the block size of a mailbox other than 0, for SDIO the block + * size on mailbox 0 is artificially set to 1. So we use the block size that is set + * for the other 3 mailboxes */ + pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; + /* must be a power of 2 */ + A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0); + + /* assemble mask, used for padding to a block */ + pDev->BlockMask = pDev->BlockSize - 1; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n", + pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX])); + + pDev->GetPendingEventsFunc = NULL; + /* see if the HIF layer implements the get pending events function */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + &pDev->GetPendingEventsFunc, + sizeof(pDev->GetPendingEventsFunc)); + + /* assume we can process HIF interrupt events asynchronously */ + pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC; + + /* see if the HIF layer overrides this assumption */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_IRQ_PROC_MODE, + &pDev->HifIRQProcessingMode, + sizeof(pDev->HifIRQProcessingMode)); + + switch (pDev->HifIRQProcessingMode) { + case HIF_DEVICE_IRQ_SYNC_ONLY: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n")); + /* see if HIF layer wants HTC to yield */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + &pDev->HifIRQYieldParams, + sizeof(pDev->HifIRQYieldParams)); + + if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("HIF requests that DSR yield per %d RECV packets \n", + pDev->HifIRQYieldParams.RecvPacketYieldCount)); + pDev->DSRCanYield = true; + } + break; + case HIF_DEVICE_IRQ_ASYNC_SYNC: + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n")); + break; + default: + A_ASSERT(false); + } + + pDev->HifMaskUmaskRecvEvent = NULL; + + /* see if the HIF layer implements the mask/unmask recv events function */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + &pDev->HifMaskUmaskRecvEvent, + sizeof(pDev->HifMaskUmaskRecvEvent)); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n", + (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent)); + + status = DevDisableInterrupts(pDev); + + if (status) { + break; + } + + status = DevSetupGMbox(pDev); + + } while (false); + + if (status) { + if (pDev->HifAttached) { + HIFDetachHTC(pDev->HIFDevice); + pDev->HifAttached = false; + } + } + + return status; + +} + +int DevEnableInterrupts(struct ar6k_device *pDev) +{ + int status; + struct ar6k_irq_enable_registers regs; + + LOCK_AR6K(pDev); + + /* Enable all the interrupts except for the internal AR6000 CPU interrupt */ + pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | + INT_STATUS_ENABLE_CPU_SET(0x01) | + INT_STATUS_ENABLE_COUNTER_SET(0x01); + + if (NULL == pDev->GetPendingEventsFunc) { + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } else { + /* The HIF layer provided us with a pending events function which means that + * the detection of pending mbox messages is handled in the HIF layer. + * This is the case for the SPI2 interface. + * In the normal case we enable MBOX interrupts, for the case + * with HIFs that offer this mechanism, we keep these interrupts + * masked */ + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } + + + /* Set up the CPU Interrupt Status Register */ + pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00); + + /* Set up the Error Interrupt Status Register */ + pDev->IrqEnableRegisters.error_status_enable = + ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) | + ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01); + + /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */ + pDev->IrqEnableRegisters.counter_int_status_enable = + COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK); + + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + /* always synchronous */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + /* Can't write it for some reason */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to update interrupt control registers err: %d\n", status)); + + } + + return status; +} + +int DevDisableInterrupts(struct ar6k_device *pDev) +{ + struct ar6k_irq_enable_registers regs; + + LOCK_AR6K(pDev); + /* Disable all interrupts */ + pDev->IrqEnableRegisters.int_status_enable = 0; + pDev->IrqEnableRegisters.cpu_int_status_enable = 0; + pDev->IrqEnableRegisters.error_status_enable = 0; + pDev->IrqEnableRegisters.counter_int_status_enable = 0; + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + /* always synchronous */ + return HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); +} + +/* enable device interrupts */ +int DevUnmaskInterrupts(struct ar6k_device *pDev) +{ + /* for good measure, make sure interrupt are disabled before unmasking at the HIF + * layer. + * The rationale here is that between device insertion (where we clear the interrupts the first time) + * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets. + * The AR6K interrupt enables reset back to an "enabled" state when this happens. + * */ + int IntStatus = 0; + DevDisableInterrupts(pDev); + +#ifdef THREAD_X + // Tobe verified... + IntStatus = DevEnableInterrupts(pDev); + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(pDev->HIFDevice); +#else + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(pDev->HIFDevice); + IntStatus = DevEnableInterrupts(pDev); +#endif + + return IntStatus; +} + +/* disable all device interrupts */ +int DevMaskInterrupts(struct ar6k_device *pDev) +{ + /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while + * we zero out our shadow registers in DevDisableInterrupts()*/ + HIFMaskInterrupt(pDev->HIFDevice); + + return DevDisableInterrupts(pDev); +} + +/* callback when our fetch to enable/disable completes */ +static void DevDoEnableDisableRecvAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Failed to disable receiver, status:%d \n", pPacket->Status)); + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n")); +} + +/* disable packet reception (used in case the host runs out of buffers) + * this is the "override" method when the HIF reports another methods to + * disable recv events */ +static int DevDoEnableDisableRecvOverride(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n", + EnableRecv,AsyncMode)); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; + pIOPacket->pContext = pDev; + + /* call the HIF layer override and do this asynchronously */ + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, + pIOPacket); + break; + } + + /* if we get here we are doing it synchronously */ + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, + NULL); + + } while (false); + + if (status && (pIOPacket != NULL)) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + +/* disable packet reception (used in case the host runs out of buffers) + * this is the "normal" method using the interrupt enable registers through + * the host I/F */ +static int DevDoEnableDisableRecvNormal(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + struct ar6k_irq_enable_registers regs; + + /* take the lock to protect interrupt enable shadows */ + LOCK_AR6K(pDev); + + if (EnableRecv) { + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } else { + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } + + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,®s,AR6K_IRQ_ENABLE_REGS_SIZE); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; + pIOPacket->pContext = pDev; + + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_ASYNC_BYTE_INC, + pIOPacket); + break; + } + + /* if we get here we are doing it synchronously */ + + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + + } while (false); + + if (status && (pIOPacket != NULL)) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + + +int DevStopRecv(struct ar6k_device *pDev, bool AsyncMode) +{ + if (NULL == pDev->HifMaskUmaskRecvEvent) { + return DevDoEnableDisableRecvNormal(pDev,false,AsyncMode); + } else { + return DevDoEnableDisableRecvOverride(pDev,false,AsyncMode); + } +} + +int DevEnableRecv(struct ar6k_device *pDev, bool AsyncMode) +{ + if (NULL == pDev->HifMaskUmaskRecvEvent) { + return DevDoEnableDisableRecvNormal(pDev,true,AsyncMode); + } else { + return DevDoEnableDisableRecvOverride(pDev,true,AsyncMode); + } +} + +int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending) +{ + int status = 0; + u8 host_int_status = 0x0; + u32 counter = 0x0; + + if(TimeoutInMs < 100) + { + TimeoutInMs = 100; + } + + counter = TimeoutInMs / 100; + + do + { + //Read the Host Interrupt Status Register + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + &host_int_status, + sizeof(u8), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) + { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status)); + break; + } + + host_int_status = !status ? (host_int_status & (1 << 0)):0; + if(!host_int_status) + { + status = 0; + *pbIsRecvPending = false; + break; + } + else + { + *pbIsRecvPending = true; + } + + A_MDELAY(100); + + counter--; + + }while(counter); + return status; +} + +void DevDumpRegisters(struct ar6k_device *pDev, + struct ar6k_irq_proc_registers *pIrqProcRegs, + struct ar6k_irq_enable_registers *pIrqEnableRegs) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n")); + + if (pIrqProcRegs != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Host Int Status: 0x%x\n",pIrqProcRegs->host_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0])); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1])); + + if (pDev->MailBoxInfo.GMboxAddress != 0) { + /* if the target supports GMBOX hardware, dump some additional state */ + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX RX Avail: 0x%x\n",pIrqProcRegs->gmbox_rx_avail)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX lookahead alias 0: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[0])); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX lookahead alias 1: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[1])); + } + + } + + if (pIrqEnableRegs != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n")); +} + + +#define DEV_GET_VIRT_DMA_INFO(p) ((struct dev_scatter_dma_virtual_info *)((p)->HIFPrivate[0])) + +static struct hif_scatter_req *DevAllocScatterReq(struct hif_device *Context) +{ + struct dl_list *pItem; + struct ar6k_device *pDev = (struct ar6k_device *)Context; + LOCK_AR6K(pDev); + pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead); + UNLOCK_AR6K(pDev); + if (pItem != NULL) { + return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink); + } + return NULL; +} + +static void DevFreeScatterReq(struct hif_device *Context, struct hif_scatter_req *pReq) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + LOCK_AR6K(pDev); + DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink); + UNLOCK_AR6K(pDev); +} + +int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA) +{ + u8 *pDMABuffer = NULL; + int i, remaining; + u32 length; + + pDMABuffer = pReq->pScatterBounceBuffer; + + if (pDMABuffer == NULL) { + A_ASSERT(false); + return A_EINVAL; + } + + remaining = (int)pReq->TotalLength; + + for (i = 0; i < pReq->ValidScatterEntries; i++) { + + length = min((int)pReq->ScatterList[i].Length, remaining); + + if (length != (int)pReq->ScatterList[i].Length) { + A_ASSERT(false); + /* there is a problem with the scatter list */ + return A_EINVAL; + } + + if (FromDMA) { + /* from DMA buffer */ + memcpy(pReq->ScatterList[i].pBuffer, pDMABuffer , length); + } else { + /* to DMA buffer */ + memcpy(pDMABuffer, pReq->ScatterList[i].pBuffer, length); + } + + pDMABuffer += length; + remaining -= length; + } + + return 0; +} + +static void DevReadWriteScatterAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + struct hif_scatter_req *pReq = (struct hif_scatter_req *)pPacket->pPktContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + pReq->CompletionStatus = pPacket->Status; + + AR6KFreeIOPacket(pDev,pPacket); + + pReq->CompletionRoutine(pReq); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n")); +} + +static int DevReadWriteScatter(struct hif_device *Context, struct hif_scatter_req *pReq) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + int status = 0; + struct htc_packet *pIOPacket = NULL; + u32 request = pReq->Request; + + do { + + if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid length: %d \n", pReq->TotalLength)); + break; + } + + if (pReq->TotalLength == 0) { + A_ASSERT(false); + break; + } + + if (request & HIF_ASYNCHRONOUS) { + /* use an I/O packet to carry this request */ + pIOPacket = AR6KAllocIOPacket(pDev); + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + break; + } + + /* save the request */ + pIOPacket->pPktContext = pReq; + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevReadWriteScatterAsyncHandler; + pIOPacket->pContext = pDev; + } + + if (request & HIF_WRITE) { + /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API + * this API will adjust the address automatically for the last byte to fall on the mailbox + * EOM. */ + + /* if the address is an extended address, we can adjust the address here since the extended + * address will bypass the normal checks in legacy HIF layers */ + if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) { + pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength; + } + } + + /* use legacy readwrite */ + status = HIFReadWrite(pDev->HIFDevice, + pReq->Address, + DEV_GET_VIRT_DMA_INFO(pReq)->pVirtDmaBuffer, + pReq->TotalLength, + request, + (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL); + + } while (false); + + if ((status != A_PENDING) && status && (request & HIF_ASYNCHRONOUS)) { + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + pReq->CompletionStatus = status; + pReq->CompletionRoutine(pReq); + status = 0; + } + + return status; +} + + +static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev) +{ + struct hif_scatter_req *pReq; + + while (1) { + pReq = DevAllocScatterReq((struct hif_device *)pDev); + if (NULL == pReq) { + break; + } + kfree(pReq); + } + +} + + /* function to set up virtual scatter support if HIF layer has not implemented the interface */ +static int DevSetupVirtualScatterSupport(struct ar6k_device *pDev) +{ + int status = 0; + int bufferSize, sgreqSize; + int i; + struct dev_scatter_dma_virtual_info *pVirtualInfo; + struct hif_scatter_req *pReq; + + bufferSize = sizeof(struct dev_scatter_dma_virtual_info) + + 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; + + sgreqSize = sizeof(struct hif_scatter_req) + + (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item)); + + for (i = 0; i < AR6K_SCATTER_REQS; i++) { + /* allocate the scatter request, buffer info and the actual virtual buffer itself */ + pReq = (struct hif_scatter_req *)A_MALLOC(sgreqSize + bufferSize); + + if (NULL == pReq) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pReq, sgreqSize); + + /* the virtual DMA starts after the scatter request struct */ + pVirtualInfo = (struct dev_scatter_dma_virtual_info *)((u8 *)pReq + sgreqSize); + A_MEMZERO(pVirtualInfo, sizeof(struct dev_scatter_dma_virtual_info)); + + pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0]; + /* align buffer to cache line in case host controller can actually DMA this */ + pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer); + /* store the structure in the private area */ + pReq->HIFPrivate[0] = pVirtualInfo; + /* we emulate a DMA bounce interface */ + pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE; + pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer; + /* free request to the list */ + DevFreeScatterReq((struct hif_device *)pDev,pReq); + } + + if (status) { + DevCleanupVirtualScatterSupport(pDev); + } else { + pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq; + pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq; + pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter; + if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n")); + pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ; + pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER; + } else { + pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ; + pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; + } + pDev->ScatterIsVirtual = true; + } + + return status; +} + +int DevCleanupMsgBundling(struct ar6k_device *pDev) +{ + if(NULL != pDev) + { + DevCleanupVirtualScatterSupport(pDev); + } + + return 0; +} + +int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer) +{ + int status; + + if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n")); + return A_ENOTSUP; + } + + status = HIFConfigureDevice(pDev->HIFDevice, + HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, + &pDev->HifScatterInfo, + sizeof(pDev->HifScatterInfo)); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status)); + + /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */ + status = DevSetupVirtualScatterSupport(pDev); + + if (!status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n", + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); + } + + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n", + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); + } + + if (!status) { + /* for the recv path, the maximum number of bytes per recv bundle is just limited + * by the maximum transfer size at the HIF layer */ + pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; + + if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n")); + pDev->MaxSendBundleSize = 0; + } else { + /* for the send path, the max transfer size is limited by the existence and size of + * the extended mailbox address range */ + if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) { + pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize; + } else { + /* legacy */ + pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH; + } + + if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) { + /* limit send bundle size to what the HIF can support for scatter requests */ + pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: max recv: %d max send: %d \n", + DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev))); + + } + return status; +} + +int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async) +{ + int status; + + if (Read) { + /* read operation */ + pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX; + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]; + A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)); + } else { + u32 mailboxWidth; + + /* write operation */ + pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC; + A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)); + if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) { + /* for large writes use the extended address */ + pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress; + mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize; + } else { + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]; + mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH; + } + + if (!pDev->ScatterIsVirtual) { + /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address + * so that the last byte falls on the EOM, we do this for those HIFs that support the + * scatter API */ + pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength); + } + + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND, + ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n", + pScatterReq->ValidScatterEntries, + pScatterReq->TotalLength, + pScatterReq->Address, + Async ? "ASYNC" : "SYNC", + (Read) ? "RD" : "WR")); + + status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq); + + if (status) { + if (Async) { + pScatterReq->CompletionStatus = status; + pScatterReq->CompletionRoutine(pScatterReq); + return 0; + } + return status; + } + + status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice, + pScatterReq); + if (!Async) { + /* in sync mode, we can touch the scatter request */ + pScatterReq->CompletionStatus = status; + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + + +#ifdef MBOXHW_UNIT_TEST + + +/* This is a mailbox hardware unit test that must be called in a schedulable context + * This test is very simple, it will send a list of buffers with a counting pattern + * and the target will invert the data and send the message back + * + * the unit test has the following constraints: + * + * The target has at least 8 buffers of 256 bytes each. The host will send + * the following pattern of buffers in rapid succession : + * + * 1 buffer - 128 bytes + * 1 buffer - 256 bytes + * 1 buffer - 512 bytes + * 1 buffer - 1024 bytes + * + * The host will send the buffers to one mailbox and wait for buffers to be reflected + * back from the same mailbox. The target sends the buffers FIFO order. + * Once the final buffer has been received for a mailbox, the next mailbox is tested. + * + * + * Note: To simplifythe test , we assume that the chosen buffer sizes + * will fall on a nice block pad + * + * It is expected that higher-order tests will be written to stress the mailboxes using + * a message-based protocol (with some performance timming) that can create more + * randomness in the packets sent over mailboxes. + * + * */ + +#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) + +#define BUFFER_BLOCK_PAD 128 + +#if 0 +#define BUFFER1 128 +#define BUFFER2 256 +#define BUFFER3 512 +#define BUFFER4 1024 +#endif + +#if 1 +#define BUFFER1 80 +#define BUFFER2 200 +#define BUFFER3 444 +#define BUFFER4 800 +#endif + +#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) ) + +#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4) + +#define TEST_CREDITS_RECV_TIMEOUT 100 + +static u8 g_Buffer[TOTAL_BYTES]; +static u32 g_MailboxAddrs[AR6K_MAILBOXES]; +static u32 g_BlockSizes[AR6K_MAILBOXES]; + +#define BUFFER_PROC_LIST_DEPTH 4 + +struct buffer_proc_list { + u8 *pBuffer; + u32 length; +}; + + +#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \ +{ \ + (pList)->pBuffer = (pCurrpos); \ + (pList)->length = (len); \ + (pCurrpos) += (len); \ + (pList)++; \ +} + +/* a simple and crude way to send different "message" sizes */ +static void AssembleBufferList(struct buffer_proc_list *pList) +{ + u8 *pBuffer = g_Buffer; + +#if BUFFER_PROC_LIST_DEPTH < 4 +#error "Buffer processing list depth is not deep enough!!" +#endif + + PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer); + +} + +#define FILL_ZERO true +#define FILL_COUNTING false +static void InitBuffers(bool Zero) +{ + u16 *pBuffer16 = (u16 *)g_Buffer; + int i; + + /* fill buffer with 16 bit counting pattern or zeros */ + for (i = 0; i < (TOTAL_BYTES / 2) ; i++) { + if (!Zero) { + pBuffer16[i] = (u16)i; + } else { + pBuffer16[i] = 0; + } + } +} + + +static bool CheckOneBuffer(u16 *pBuffer16, int Length) +{ + int i; + u16 startCount; + bool success = true; + + /* get the starting count */ + startCount = pBuffer16[0]; + /* invert it, this is the expected value */ + startCount = ~startCount; + /* scan the buffer and verify */ + for (i = 0; i < (Length / 2) ; i++,startCount++) { + /* target will invert all the data */ + if ((u16)pBuffer16[i] != (u16)~startCount) { + success = false; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n", + pBuffer16[i], ((u16)~startCount), i, Length)); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n", + pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3])); + break; + } + } + + return success; +} + +static bool CheckBuffers(void) +{ + int i; + bool success = true; + struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH]; + + /* assemble the list */ + AssembleBufferList(checkList); + + /* scan the buffers and verify */ + for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) { + success = CheckOneBuffer((u16 *)checkList[i].pBuffer, checkList[i].length); + if (!success) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n", + (u32)checkList[i].pBuffer, checkList[i].length)); + break; + } + } + + return success; +} + + /* find the end marker for the last buffer we will be sending */ +static u16 GetEndMarker(void) +{ + u8 *pBuffer; + struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH]; + + /* fill up buffers with the normal counting pattern */ + InitBuffers(FILL_COUNTING); + + /* assemble the list we will be sending down */ + AssembleBufferList(checkList); + /* point to the last 2 bytes of the last buffer */ + pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]); + + /* the last count in the last buffer is the marker */ + return (u16)pBuffer[0] | ((u16)pBuffer[1] << 8); +} + +#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR + +/* send the ordered buffers to the target */ +static int SendBuffers(struct ar6k_device *pDev, int mbox) +{ + int status = 0; + u32 request = HIF_WR_SYNC_BLOCK_INC; + struct buffer_proc_list sendList[BUFFER_PROC_LIST_DEPTH]; + int i; + int totalBytes = 0; + int paddedLength; + int totalwPadding = 0; + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox)); + + /* fill buffer with counting pattern */ + InitBuffers(FILL_COUNTING); + + /* assemble the order in which we send */ + AssembleBufferList(sendList); + + for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) { + + /* we are doing block transfers, so we need to pad everything to a block size */ + paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) & + (~(g_BlockSizes[mbox] - 1)); + + /* send each buffer synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + g_MailboxAddrs[mbox], + sendList[i].pBuffer, + paddedLength, + request, + NULL); + if (status) { + break; + } + totalBytes += sendList[i].length; + totalwPadding += paddedLength; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox)); + + return status; +} + +/* poll the mailbox credit counter until we get a credit or timeout */ +static int GetCredits(struct ar6k_device *pDev, int mbox, int *pCredits) +{ + int status = 0; + int timeout = TEST_CREDITS_RECV_TIMEOUT; + u8 credits = 0; + u32 address; + + while (true) { + + /* Read the counter register to get credits, this auto-decrements */ + address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4; + status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits), + HIF_RD_SYNC_BYTE_FIX, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to decrement the command credit count register (mbox=%d)\n",mbox)); + status = A_ERROR; + break; + } + + if (credits) { + break; + } + + timeout--; + + if (timeout <= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address)); + status = A_ERROR; + break; + } + + /* delay a little, target may not be ready */ + A_MDELAY(1000); + + } + + if (status == 0) { + *pCredits = credits; + } + + return status; +} + + +/* wait for the buffers to come back */ +static int RecvBuffers(struct ar6k_device *pDev, int mbox) +{ + int status = 0; + u32 request = HIF_RD_SYNC_BLOCK_INC; + struct buffer_proc_list recvList[BUFFER_PROC_LIST_DEPTH]; + int curBuffer; + int credits; + int i; + int totalBytes = 0; + int paddedLength; + int totalwPadding = 0; + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox)); + + /* zero the buffers */ + InitBuffers(FILL_ZERO); + + /* assemble the order in which we should receive */ + AssembleBufferList(recvList); + + curBuffer = 0; + + while (curBuffer < BUFFER_PROC_LIST_DEPTH) { + + /* get number of buffers that have been completed, this blocks + * until we get at least 1 credit or it times out */ + status = GetCredits(pDev, mbox, &credits); + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox)); + + /* get all the buffers that are sitting on the queue */ + for (i = 0; i < credits; i++) { + A_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH); + /* recv the current buffer synchronously, the buffers should come back in + * order... with padding applied by the target */ + paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) & + (~(g_BlockSizes[mbox] - 1)); + + status = HIFReadWrite(pDev->HIFDevice, + g_MailboxAddrs[mbox], + recvList[curBuffer].pBuffer, + paddedLength, + request, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n", + recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox])); + break; + } + + totalwPadding += paddedLength; + totalBytes += recvList[curBuffer].length; + curBuffer++; + } + + if (status) { + break; + } + /* go back and get some more */ + credits = 0; + } + + if (totalBytes != TEST_BYTES) { + A_ASSERT(false); + } else { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n", + mbox, totalBytes, totalwPadding)); + } + + return status; + + +} + +static int DoOneMboxHWTest(struct ar6k_device *pDev, int mbox) +{ + int status; + + do { + /* send out buffers */ + status = SendBuffers(pDev,mbox); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox)); + break; + } + + /* go get them, this will block */ + status = RecvBuffers(pDev, mbox); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox)); + break; + } + + /* check the returned data patterns */ + if (!CheckBuffers()) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox)); + status = A_ERROR; + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox)); + + } while (false); + + return status; +} + +/* here is where the test starts */ +int DoMboxHWTest(struct ar6k_device *pDev) +{ + int i; + int status; + int credits = 0; + u8 params[4]; + int numBufs; + int bufferSize; + u16 temp; + + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n")); + + do { + /* get the addresses for all 4 mailboxes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, + g_MailboxAddrs, sizeof(g_MailboxAddrs)); + + if (status) { + A_ASSERT(false); + break; + } + + /* get the block sizes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + g_BlockSizes, sizeof(g_BlockSizes)); + + if (status) { + A_ASSERT(false); + break; + } + + /* note, the HIF layer usually reports mbox 0 to have a block size of + * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes + * the same. */ + g_BlockSizes[0] = g_BlockSizes[1]; + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0])); + + if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n", + g_BlockSizes[1], BUFFER_BLOCK_PAD)); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n")); + + /* the target lets us know it is ready by giving us 1 credit on + * mailbox 0 */ + status = GetCredits(pDev, 0, &credits); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n")); + + /* read the first 4 scratch registers */ + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS, + params, + 4, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n")); + break; + } + + numBufs = params[0]; + bufferSize = (int)(((u16)params[2] << 8) | (u16)params[1]); + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, + ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n", + numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES)); + + if ((numBufs * bufferSize) < TOTAL_BYTES) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n", + TOTAL_BYTES, (numBufs*bufferSize))); + status = A_ERROR; + break; + } + + temp = GetEndMarker(); + + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS + 4, + (u8 *)&temp, + 2, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp)); + + temp = (u16)g_BlockSizes[1]; + /* convert to a mask */ + temp = temp - 1; + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS + 6, + (u8 *)&temp, + 2, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp)); + + /* execute the test on each mailbox */ + for (i = 0; i < AR6K_MAILBOXES; i++) { + status = DoOneMboxHWTest(pDev, i); + if (status) { + break; + } + } + + } while (false); + + if (status == 0) { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n")); + } else { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n")); + } + /* don't let HTC_Start continue, the target is actually not running any HTC code */ + return A_ERROR; +} +#endif + + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h new file mode 100644 index 000000000000..e551dbe674dc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h @@ -0,0 +1,401 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K device layer that handles register level I/O +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef AR6K_H_ +#define AR6K_H_ + +#include "hci_transport_api.h" +#include "../htc_debug.h" + +#define AR6K_MAILBOXES 4 + +/* HTC runs over mailbox 0 */ +#define HTC_MAILBOX 0 + +#define AR6K_TARGET_DEBUG_INTR_MASK 0x01 + +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ + INT_STATUS_ENABLE_CPU_MASK | \ + INT_STATUS_ENABLE_COUNTER_MASK) + + +//#define MBOXHW_UNIT_TEST 1 + +PREPACK struct ar6k_irq_proc_registers { + u8 host_int_status; + u8 cpu_int_status; + u8 error_int_status; + u8 counter_int_status; + u8 mbox_frame; + u8 rx_lookahead_valid; + u8 host_int_status2; + u8 gmbox_rx_avail; + u32 rx_lookahead[2]; + u32 rx_gmbox_lookahead_alias[2]; +} POSTPACK; + +#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers) + +PREPACK struct ar6k_irq_enable_registers { + u8 int_status_enable; + u8 cpu_int_status_enable; + u8 error_status_enable; + u8 counter_int_status_enable; +} POSTPACK; + +PREPACK struct ar6k_gmbox_ctrl_registers { + u8 int_status_enable; +} POSTPACK; + +#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers) + +#define AR6K_REG_IO_BUFFER_SIZE 32 +#define AR6K_MAX_REG_IO_BUFFERS 8 +#define FROM_DMA_BUFFER true +#define TO_DMA_BUFFER false +#define AR6K_SCATTER_ENTRIES_PER_REQ 16 +#define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024 +#define AR6K_SCATTER_REQS 4 +#define AR6K_LEGACY_MAX_WRITE_LENGTH 2048 + +#ifndef A_CACHE_LINE_PAD +#define A_CACHE_LINE_PAD 128 +#endif +#define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2 +#define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024 + +/* buffers for ASYNC I/O */ +struct ar6k_async_reg_io_buffer { + struct htc_packet HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */ + u8 _Pad1[A_CACHE_LINE_PAD]; + u8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; /* cache-line safe with pads around */ + u8 _Pad2[A_CACHE_LINE_PAD]; +}; + +struct ar6k_gmbox_info { + void *pProtocolContext; + int (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes); + int (*pCreditsPendingCallback)(void *pContext, int NumCredits, bool CreditIRQEnabled); + void (*pTargetFailureCallback)(void *pContext, int Status); + void (*pStateDumpCallback)(void *pContext); + bool CreditCountIRQEnabled; +}; + +struct ar6k_device { + A_MUTEX_T Lock; + u8 _Pad1[A_CACHE_LINE_PAD]; + struct ar6k_irq_proc_registers IrqProcRegisters; /* cache-line safe with pads around */ + u8 _Pad2[A_CACHE_LINE_PAD]; + struct ar6k_irq_enable_registers IrqEnableRegisters; /* cache-line safe with pads around */ + u8 _Pad3[A_CACHE_LINE_PAD]; + void *HIFDevice; + u32 BlockSize; + u32 BlockMask; + struct hif_device_mbox_info MailBoxInfo; + HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc; + void *HTCContext; + struct htc_packet_queue RegisterIOList; + struct ar6k_async_reg_io_buffer RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS]; + void (*TargetFailureCallback)(void *Context); + int (*MessagePendingCallback)(void *Context, + u32 LookAheads[], + int NumLookAheads, + bool *pAsyncProc, + int *pNumPktsFetched); + HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; + HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; + bool HifAttached; + struct hif_device_irq_yield_params HifIRQYieldParams; + bool DSRCanYield; + int CurrentDSRRecvCount; + struct hif_device_scatter_support_info HifScatterInfo; + struct dl_list ScatterReqHead; + bool ScatterIsVirtual; + int MaxRecvBundleSize; + int MaxSendBundleSize; + struct ar6k_gmbox_info GMboxInfo; + bool GMboxEnabled; + struct ar6k_gmbox_ctrl_registers GMboxControlRegisters; + int RecheckIRQStatusCnt; +}; + +#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock); +#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock); +#define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need to lock this, it only gets set */ + +int DevSetup(struct ar6k_device *pDev); +void DevCleanup(struct ar6k_device *pDev); +int DevUnmaskInterrupts(struct ar6k_device *pDev); +int DevMaskInterrupts(struct ar6k_device *pDev); +int DevPollMboxMsgRecv(struct ar6k_device *pDev, + u32 *pLookAhead, + int TimeoutMS); +int DevRWCompletionHandler(void *context, int status); +int DevDsrHandler(void *context); +int DevCheckPendingRecvMsgsAsync(void *context); +void DevAsyncIrqProcessComplete(struct ar6k_device *pDev); +void DevDumpRegisters(struct ar6k_device *pDev, + struct ar6k_irq_proc_registers *pIrqProcRegs, + struct ar6k_irq_enable_registers *pIrqEnableRegs); + +#define DEV_STOP_RECV_ASYNC true +#define DEV_STOP_RECV_SYNC false +#define DEV_ENABLE_RECV_ASYNC true +#define DEV_ENABLE_RECV_SYNC false +int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode); +int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode); +int DevEnableInterrupts(struct ar6k_device *pDev); +int DevDisableInterrupts(struct ar6k_device *pDev); +int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending); + +#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask))) +#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length) +#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0) + +static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) { + u32 paddedLength; + bool sync = (pPacket->Completion == NULL) ? true : false; + int status; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength); + +#if 0 + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", + paddedLength, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + pPacket->pBuffer, + paddedLength, /* the padded length */ + sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + +static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) { + u32 paddedLength; + int status; + bool sync = (pPacket->Completion == NULL) ? true : false; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength); + + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", + paddedLength,RecvLength,pPacket->BufferLength)); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, + paddedLength, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + pPacket->pBuffer, + paddedLength, + sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } + + return status; +} + +#define DEV_CHECK_RECV_YIELD(pDev) \ + ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount) + +#define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode) +#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY) + +/**************************************************/ +/****** Scatter Function and Definitions + * + * + */ + +int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA); + + /* copy any READ data back into scatter list */ +#define DEV_FINISH_SCATTER_OPERATION(pR) \ +do { \ + if (!((pR)->CompletionStatus) && \ + !((pR)->Request & HIF_WRITE) && \ + ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \ + (pR)->CompletionStatus = \ + DevCopyScatterListToFromDMABuffer((pR), \ + FROM_DMA_BUFFER); \ + } \ +} while (0) + + /* copy any WRITE data to bounce buffer */ +static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq) { + if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { + return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER); + } else { + return 0; + } +} + + +int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer); + +int DevCleanupMsgBundling(struct ar6k_device *pDev); + +#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatterEntries +#define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq +#define DEV_ALLOC_SCATTER_REQ(pDev) \ + (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice) + +#define DEV_FREE_SCATTER_REQ(pDev,pR) \ + (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR)) + +#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize +#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize + +#define DEV_SCATTER_READ true +#define DEV_SCATTER_WRITE false +#define DEV_SCATTER_ASYNC true +#define DEV_SCATTER_SYNC false +int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async); + +#ifdef MBOXHW_UNIT_TEST +int DoMboxHWTest(struct ar6k_device *pDev); +#endif + + /* completely virtual */ +struct dev_scatter_dma_virtual_info { + u8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible address */ + u8 DataArea[1]; /* start of data area */ +}; + + + +void DumpAR6KDevState(struct ar6k_device *pDev); + +/**************************************************/ +/****** GMBOX functions and definitions + * + * + */ + +#ifdef ATH_AR6K_ENABLE_GMBOX + +void DevCleanupGMbox(struct ar6k_device *pDev); +int DevSetupGMbox(struct ar6k_device *pDev); +int DevCheckGMboxInterrupts(struct ar6k_device *pDev); +void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev); + +#else + + /* compiled out */ +#define DevCleanupGMbox(p) +#define DevCheckGMboxInterrupts(p) 0 +#define DevNotifyGMboxTargetFailure(p) + +static INLINE int DevSetupGMbox(struct ar6k_device *pDev) { + pDev->GMboxEnabled = false; + return 0; +} + +#endif + +#ifdef ATH_AR6K_ENABLE_GMBOX + + /* GMBOX protocol modules must expose each of these internal APIs */ +HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo); +int GMboxProtocolInstall(struct ar6k_device *pDev); +void GMboxProtocolUninstall(struct ar6k_device *pDev); + + /* API used by GMBOX protocol modules */ +struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle); +#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \ +{ \ + (pDev)->GMboxInfo.pProtocolContext = (context); \ + (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \ + (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \ + (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \ + (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \ +} + +#define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext + +int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength); +int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength); + +#define PROC_IO_ASYNC true +#define PROC_IO_SYNC false +typedef enum GMBOX_IRQ_ACTION_TYPE { + GMBOX_ACTION_NONE = 0, + GMBOX_DISABLE_ALL, + GMBOX_ERRORS_IRQ_ENABLE, + GMBOX_RECV_IRQ_ENABLE, + GMBOX_RECV_IRQ_DISABLE, + GMBOX_CREDIT_IRQ_ENABLE, + GMBOX_CREDIT_IRQ_DISABLE, +} GMBOX_IRQ_ACTION_TYPE; + +int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode); +int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits); +int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize); +int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes); +int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS); + +#endif + +#endif /*AR6K_H_*/ diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c new file mode 100644 index 000000000000..d7af68f70560 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c @@ -0,0 +1,783 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K Driver layer event handling (i.e. interrupts, message polling) +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "hw/mbox_host_reg.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" + +extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket); +extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev); + +static int DevServiceDebugInterrupt(struct ar6k_device *pDev); + +#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */ + +/* completion routine for ALL HIF layer async I/O */ +int DevRWCompletionHandler(void *context, int status) +{ + struct htc_packet *pPacket = (struct htc_packet *)context; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n", + (unsigned long)pPacket, + status)); + + COMPLETE_HTC_PACKET(pPacket,status); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("-DevRWCompletionHandler\n")); + + return 0; +} + +/* mailbox recv message polling */ +int DevPollMboxMsgRecv(struct ar6k_device *pDev, + u32 *pLookAhead, + int TimeoutMS) +{ + int status = 0; + int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS; + + A_ASSERT(timeout > 0); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n")); + + while (true) { + + if (pDev->GetPendingEventsFunc != NULL) { + + struct hif_pending_events_info events; + +#ifdef THREAD_X + events.Polling =1; +#endif + + /* the HIF layer uses a special mechanism to get events, do this + * synchronously */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + &events, + NULL); + if (status) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n")); + break; + } + + if (events.Events & HIF_RECV_MSG_AVAIL) + { + /* there is a message available, the lookahead should be valid now */ + *pLookAhead = events.LookAhead; + + break; + } + } else { + + /* this is the standard HIF way.... */ + /* load the register table */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&pDev->IrqProcRegisters, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n")); + break; + } + + /* check for MBOX data and valid lookahead */ + if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) { + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) + { + /* mailbox has a message and the look ahead is valid */ + *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; + break; + } + } + + } + + timeout--; + + if (timeout <= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n")); + status = A_ERROR; + + /* check if the target asserted */ + if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { + /* target signaled an assert, process this pending interrupt + * this will call the target failure handler */ + DevServiceDebugInterrupt(pDev); + } + + break; + } + + /* delay a little */ + A_MDELAY(DELAY_PER_INTERVAL_MS); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n")); + + return status; +} + +static int DevServiceCPUInterrupt(struct ar6k_device *pDev) +{ + int status; + u8 cpu_int_status; + u8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n")); + cpu_int_status = pDev->IrqProcRegisters.cpu_int_status & + pDev->IrqEnableRegisters.cpu_int_status_enable; + A_ASSERT(cpu_int_status); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", + cpu_int_status)); + + /* Clear the interrupt */ + pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = cpu_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + CPU_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == 0); + return status; +} + + +static int DevServiceErrorInterrupt(struct ar6k_device *pDev) +{ + int status; + u8 error_int_status; + u8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n")); + error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F; + A_ASSERT(error_int_status); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", + error_int_status)); + + if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { + /* Wakeup */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n")); + } + + if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { + /* Rx Underflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n")); + } + + if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { + /* Tx Overflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n")); + } + + /* Clear the interrupt */ + pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = error_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + ERROR_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == 0); + return status; +} + +static int DevServiceDebugInterrupt(struct ar6k_device *pDev) +{ + u32 dummy; + int status; + + /* Send a target failure event to the application */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); + + if (pDev->TargetFailureCallback != NULL) { + pDev->TargetFailureCallback(pDev->HTCContext); + } + + if (pDev->GMboxEnabled) { + DevNotifyGMboxTargetFailure(pDev); + } + + /* clear the interrupt , the debug error interrupt is + * counter 0 */ + /* read counter to clear interrupt */ + status = HIFReadWrite(pDev->HIFDevice, + COUNT_DEC_ADDRESS, + (u8 *)&dummy, + 4, + HIF_RD_SYNC_BYTE_INC, + NULL); + + A_ASSERT(status == 0); + return status; +} + +static int DevServiceCounterInterrupt(struct ar6k_device *pDev) +{ + u8 counter_int_status; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n")); + + counter_int_status = pDev->IrqProcRegisters.counter_int_status & + pDev->IrqEnableRegisters.counter_int_status_enable; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", + counter_int_status)); + + /* Check if the debug interrupt is pending + * NOTE: other modules like GMBOX may use the counter interrupt for + * credit flow control on other counters, we only need to check for the debug assertion + * counter interrupt */ + if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { + return DevServiceDebugInterrupt(pDev); + } + + return 0; +} + +/* callback when our fetch to get interrupt status registers completes */ +static void DevGetEventAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + u32 lookAhead = 0; + bool otherInts = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + do { + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" GetEvents I/O request failed, status:%d \n", pPacket->Status)); + /* bail out, don't unmask HIF interrupt */ + break; + } + + if (pDev->GetPendingEventsFunc != NULL) { + /* the HIF layer collected the information for us */ + struct hif_pending_events_info *pEvents = (struct hif_pending_events_info *)pPacket->pBuffer; + if (pEvents->Events & HIF_RECV_MSG_AVAIL) { + lookAhead = pEvents->LookAhead; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n")); + } + } + if (pEvents->Events & HIF_OTHER_EVENTS) { + otherInts = true; + } + } else { + /* standard interrupt table handling.... */ + struct ar6k_irq_proc_registers *pReg = (struct ar6k_irq_proc_registers *)pPacket->pBuffer; + u8 host_int_status; + + host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable; + + if (host_int_status & (1 << HTC_MAILBOX)) { + host_int_status &= ~(1 << HTC_MAILBOX); + if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) { + /* mailbox has a message and the look ahead is valid */ + lookAhead = pReg->rx_lookahead[HTC_MAILBOX]; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n")); + } + } + } + + if (host_int_status) { + /* there are other interrupts to handle */ + otherInts = true; + } + } + + if (otherInts || (lookAhead == 0)) { + /* if there are other interrupts to process, we cannot do this in the async handler so + * ack the interrupt which will cause our sync handler to run again + * if however there are no more messages, we can now ack the interrupt */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n", + otherInts, lookAhead)); + HIFAckInterrupt(pDev->HIFDevice); + } else { + int fetched = 0; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n", + lookAhead)); + /* lookahead is non-zero and there are no other interrupts to service, + * go get the next message */ + status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched); + + if (!status && !fetched) { + /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n")); + DevAsyncIrqProcessComplete(pDev); + } + } + + } while (false); + + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); +} + +/* called by the HTC layer when it wants us to check if the device has any more pending + * recv messages, this starts off a series of async requests to read interrupt registers */ +int DevCheckPendingRecvMsgsAsync(void *context) +{ + struct ar6k_device *pDev = (struct ar6k_device *)context; + int status = 0; + struct htc_packet *pIOPacket; + + /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can + * cause us to switch contexts */ + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%lX)\n", (unsigned long)pDev)); + + do { + + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { + /* break the async processing chain right here, no need to continue. + * The DevDsrHandler() will handle things in a loop when things are driven + * synchronously */ + break; + } + + /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake + * the target, if upper layers determine that we are in a low-throughput mode, we can + * rely on taking another interrupt rather than re-checking the status registers which can + * re-wake the target */ + if (pDev->RecheckIRQStatusCnt == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-acking HIF interrupts\n")); + /* ack interrupt */ + HIFAckInterrupt(pDev->HIFDevice); + break; + } + + /* first allocate one of our HTC packets we created for async I/O + * we reuse HTC packet definitions so that we can use the completion mechanism + * in DevRWCompletionHandler() */ + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + /* there should be only 1 asynchronous request out at a time to read these registers + * so this should actually never happen */ + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGetEventAsyncHandler; + pIOPacket->pContext = pDev; + + if (pDev->GetPendingEventsFunc) { + /* HIF layer has it's own mechanism, pass the IO to it.. */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + (struct hif_pending_events_info *)pIOPacket->pBuffer, + pIOPacket); + + } else { + /* standard way, read the interrupt register table asynchronously again */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_ASYNC_BYTE_INC, + pIOPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n")); + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); + + return status; +} + +void DevAsyncIrqProcessComplete(struct ar6k_device *pDev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n")); + HIFAckInterrupt(pDev->HIFDevice); +} + +/* process pending interrupts synchronously */ +static int ProcessPendingIRQs(struct ar6k_device *pDev, bool *pDone, bool *pASyncProcessing) +{ + int status = 0; + u8 host_int_status = 0; + u32 lookAhead = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /*** NOTE: the HIF implementation guarantees that the context of this call allows + * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that + * can block or switch thread/task ontexts. + * This is a fully schedulable context. + * */ + do { + + if (pDev->IrqEnableRegisters.int_status_enable == 0) { + /* interrupt enables have been cleared, do not try to process any pending interrupts that + * may result in more bus transactions. The target may be unresponsive at this + * point. */ + break; + } + + if (pDev->GetPendingEventsFunc != NULL) { + struct hif_pending_events_info events; + +#ifdef THREAD_X + events.Polling= 0; +#endif + /* the HIF layer uses a special mechanism to get events + * get this synchronously */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + &events, + NULL); + + if (status) { + break; + } + + if (events.Events & HIF_RECV_MSG_AVAIL) { + lookAhead = events.LookAhead; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n")); + } + } + + if (!(events.Events & HIF_OTHER_EVENTS) || + !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) { + /* no need to read the register table, no other interesting interrupts. + * Some interfaces (like SPI) can shadow interrupt sources without + * requiring the host to do a full table read */ + break; + } + + /* otherwise fall through and read the register table */ + } + + /* + * Read the first 28 bytes of the HTC register table. This will yield us + * the value of different int status registers and the lookahead + * registers. + * length = sizeof(int_status) + sizeof(cpu_int_status) + + * sizeof(error_int_status) + sizeof(counter_int_status) + + * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) + + * sizeof(hole) + sizeof(rx_lookahead) + + * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) + + * sizeof(error_status_enable) + + * sizeof(counter_int_status_enable); + * + */ +#ifdef CONFIG_MMC_SDHCI_S3C + pDev->IrqProcRegisters.host_int_status = 0; + pDev->IrqProcRegisters.rx_lookahead_valid = 0; + pDev->IrqProcRegisters.host_int_status2 = 0; + pDev->IrqProcRegisters.rx_lookahead[0] = 0; + pDev->IrqProcRegisters.rx_lookahead[1] = 0xaaa5555; +#endif /* CONFIG_MMC_SDHCI_S3C */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&pDev->IrqProcRegisters, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + break; + } + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { + DevDumpRegisters(pDev, + &pDev->IrqProcRegisters, + &pDev->IrqEnableRegisters); + } +#endif + + /* Update only those registers that are enabled */ + host_int_status = pDev->IrqProcRegisters.host_int_status & + pDev->IrqEnableRegisters.int_status_enable; + + if (NULL == pDev->GetPendingEventsFunc) { + /* only look at mailbox status if the HIF layer did not provide this function, + * on some HIF interfaces reading the RX lookahead is not valid to do */ + if (host_int_status & (1 << HTC_MAILBOX)) { + /* mask out pending mailbox value, we use "lookAhead" as the real flag for + * mailbox processing below */ + host_int_status &= ~(1 << HTC_MAILBOX); + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) { + /* mailbox has a message and the look ahead is valid */ + lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n")); + } + } + } + } else { + /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/ + host_int_status &= ~(1 << HTC_MAILBOX); + } + + if (pDev->GMboxEnabled) { + /*call GMBOX layer to process any interrupts of interest */ + status = DevCheckGMboxInterrupts(pDev); + } + + } while (false); + + + do { + + /* did the interrupt status fetches succeed? */ + if (status) { + break; + } + + if ((0 == host_int_status) && (0 == lookAhead)) { + /* nothing to process, the caller can use this to break out of a loop */ + *pDone = true; + break; + } + + if (lookAhead != 0) { + int fetched = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead)); + /* Mailbox Interrupt, the HTC layer may issue async requests to empty the + * mailbox... + * When emptying the recv mailbox we use the async handler above called from the + * completion routine of the callers read request. This can improve performance + * by reducing context switching when we rapidly pull packets */ + status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched); + if (status) { + break; + } + + if (!fetched) { + /* HTC could not pull any messages out due to lack of resources */ + /* force DSR handler to ack the interrupt */ + *pASyncProcessing = false; + pDev->RecheckIRQStatusCnt = 0; + } + } + + /* now handle the rest of them */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n", + host_int_status)); + + if (HOST_INT_STATUS_CPU_GET(host_int_status)) { + /* CPU Interrupt */ + status = DevServiceCPUInterrupt(pDev); + if (status){ + break; + } + } + + if (HOST_INT_STATUS_ERROR_GET(host_int_status)) { + /* Error Interrupt */ + status = DevServiceErrorInterrupt(pDev); + if (status){ + break; + } + } + + if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) { + /* Counter Interrupt */ + status = DevServiceCounterInterrupt(pDev); + if (status){ + break; + } + } + + } while (false); + + /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake + * the target, if upper layers determine that we are in a low-throughput mode, we can + * rely on taking another interrupt rather than re-checking the status registers which can + * re-wake the target. + * + * NOTE : for host interfaces that use the special GetPendingEventsFunc, this optimization cannot + * be used due to possible side-effects. For example, SPI requires the host to drain all + * messages from the mailbox before exiting the ISR routine. */ + if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n")); + *pDone = true; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n", + *pDone, *pASyncProcessing, status)); + + return status; +} + + +/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/ +int DevDsrHandler(void *context) +{ + struct ar6k_device *pDev = (struct ar6k_device *)context; + int status = 0; + bool done = false; + bool asyncProc = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /* reset the recv counter that tracks when we need to yield from the DSR */ + pDev->CurrentDSRRecvCount = 0; + /* reset counter used to flag a re-scan of IRQ status registers on the target */ + pDev->RecheckIRQStatusCnt = 0; + + while (!done) { + status = ProcessPendingIRQs(pDev, &done, &asyncProc); + if (status) { + break; + } + + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { + /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */ + asyncProc = false; + /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers. + * this has a nice side effect of blocking us until all async read requests are completed. + * This behavior is required on some HIF implementations that do not allow ASYNC + * processing in interrupt handlers (like Windows CE) */ + + if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { + /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop + * checking for more messages and return */ + break; + } + } + + if (asyncProc) { + /* the function performed some async I/O for performance, we + need to exit the ISR immediately, the check below will prevent the interrupt from being + Ack'd while we handle it asynchronously */ + break; + } + + } + + if (!status && !asyncProc) { + /* Ack the interrupt only if : + * 1. we did not get any errors in processing interrupts + * 2. there are no outstanding async processing requests */ + if (pDev->DSRCanYield) { + /* if the DSR can yield do not ACK the interrupt, there could be more pending messages. + * The HIF layer must ACK the interrupt on behalf of HTC */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n")); + HIFAckInterrupt(pDev->HIFDevice); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); + return status; +} + +#ifdef ATH_DEBUG_MODULE +void DumpAR6KDevState(struct ar6k_device *pDev) +{ + int status; + struct ar6k_irq_enable_registers regs; + struct ar6k_irq_proc_registers procRegs; + + LOCK_AR6K(pDev); + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + UNLOCK_AR6K(pDev); + + /* load the register table from the device */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&procRegs, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DumpAR6KDevState : Failed to read register table (%d) \n",status)); + return; + } + + DevDumpRegisters(pDev,&procRegs,®s); + + if (pDev->GMboxInfo.pStateDumpCallback != NULL) { + pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext); + } + + /* dump any bus state at the HIF layer */ + HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0); + +} +#endif + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c new file mode 100644 index 000000000000..725540f9adde --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c @@ -0,0 +1,755 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Generic MBOX API implementation +// +// Author(s): ="Atheros" +//============================================================================== +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" +#include "hw/mbox_host_reg.h" +#include "gmboxif.h" + +/* + * This file provides management functions and a toolbox for GMBOX protocol modules. + * Only one protocol module can be installed at a time. The determination of which protocol + * module is installed is determined at compile time. + * + */ +#ifdef ATH_AR6K_ENABLE_GMBOX + /* GMBOX definitions */ +#define GMBOX_INT_STATUS_ENABLE_REG 0x488 +#define GMBOX_INT_STATUS_RX_DATA (1 << 0) +#define GMBOX_INT_STATUS_TX_OVERFLOW (1 << 1) +#define GMBOX_INT_STATUS_RX_OVERFLOW (1 << 2) + +#define GMBOX_LOOKAHEAD_MUX_REG 0x498 +#define GMBOX_LA_MUX_OVERRIDE_2_3 (1 << 0) + +#define AR6K_GMBOX_CREDIT_DEC_ADDRESS (COUNT_DEC_ADDRESS + 4 * AR6K_GMBOX_CREDIT_COUNTER) +#define AR6K_GMBOX_CREDIT_SIZE_ADDRESS (COUNT_ADDRESS + AR6K_GMBOX_CREDIT_SIZE_COUNTER) + + + /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */ +extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket); +extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev); + + +/* callback when our fetch to enable/disable completes */ +static void DevGMboxIRQActionAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status)); + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n")); +} + +static int DevGMboxCounterEnableDisable(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode) +{ + int status = 0; + struct ar6k_irq_enable_registers regs; + struct htc_packet *pIOPacket = NULL; + + LOCK_AR6K(pDev); + + if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) { + pDev->GMboxInfo.CreditCountIRQEnabled = true; + pDev->IrqEnableRegisters.counter_int_status_enable |= + COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER); + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01); + } else { + pDev->GMboxInfo.CreditCountIRQEnabled = false; + pDev->IrqEnableRegisters.counter_int_status_enable &= + ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER)); + } + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxIRQActionAsyncHandler; + pIOPacket->pContext = pDev; + pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction; + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_ASYNC_BYTE_INC, + pIOPacket); + + pIOPacket = NULL; + break; + } + + /* if we get here we are doing it synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status)); + } else { + if (!AsyncMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" IRQAction Operation (%d) success \n", IrqAction)); + } + } + + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + + +int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + u8 GMboxIntControl[4]; + + if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) { + return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode); + } else if(GMBOX_CREDIT_IRQ_DISABLE == IrqAction) { + return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode); + } + + if (GMBOX_DISABLE_ALL == IrqAction) { + /* disable credit IRQ, those are on a different set of registers */ + DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode); + } + + /* take the lock to protect interrupt enable shadows */ + LOCK_AR6K(pDev); + + switch (IrqAction) { + + case GMBOX_DISABLE_ALL: + pDev->GMboxControlRegisters.int_status_enable = 0; + break; + case GMBOX_ERRORS_IRQ_ENABLE: + pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_TX_OVERFLOW | + GMBOX_INT_STATUS_RX_OVERFLOW; + break; + case GMBOX_RECV_IRQ_ENABLE: + pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_RX_DATA; + break; + case GMBOX_RECV_IRQ_DISABLE: + pDev->GMboxControlRegisters.int_status_enable &= ~GMBOX_INT_STATUS_RX_DATA; + break; + case GMBOX_ACTION_NONE: + default: + A_ASSERT(false); + break; + } + + GMboxIntControl[0] = pDev->GMboxControlRegisters.int_status_enable; + GMboxIntControl[1] = GMboxIntControl[0]; + GMboxIntControl[2] = GMboxIntControl[0]; + GMboxIntControl[3] = GMboxIntControl[0]; + + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl)); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxIRQActionAsyncHandler; + pIOPacket->pContext = pDev; + pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction; + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + GMBOX_INT_STATUS_ENABLE_REG, + pIOPacket->pBuffer, + sizeof(GMboxIntControl), + HIF_WR_ASYNC_BYTE_FIX, + pIOPacket); + pIOPacket = NULL; + break; + } + + /* if we get here we are doing it synchronously */ + + status = HIFReadWrite(pDev->HIFDevice, + GMBOX_INT_STATUS_ENABLE_REG, + GMboxIntControl, + sizeof(GMboxIntControl), + HIF_WR_SYNC_BYTE_FIX, + NULL); + + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status)); + } else { + if (!AsyncMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" IRQAction Operation (%d) success \n", IrqAction)); + } + } + + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + +void DevCleanupGMbox(struct ar6k_device *pDev) +{ + if (pDev->GMboxEnabled) { + pDev->GMboxEnabled = false; + GMboxProtocolUninstall(pDev); + } +} + +int DevSetupGMbox(struct ar6k_device *pDev) +{ + int status = 0; + u8 muxControl[4]; + + do { + + if (0 == pDev->MailBoxInfo.GMboxAddress) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n", + pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize)); + + status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC); + + if (status) { + break; + } + + /* write to mailbox look ahead mux control register, we want the + * GMBOX lookaheads to appear on lookaheads 2 and 3 + * the register is 1-byte wide so we need to hit it 4 times to align the operation + * to 4-bytes */ + muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3; + + status = HIFReadWrite(pDev->HIFDevice, + GMBOX_LOOKAHEAD_MUX_REG, + muxControl, + sizeof(muxControl), + HIF_WR_SYNC_BYTE_FIX, /* hit this register 4 times */ + NULL); + + if (status) { + break; + } + + status = GMboxProtocolInstall(pDev); + + if (status) { + break; + } + + pDev->GMboxEnabled = true; + + } while (false); + + return status; +} + +int DevCheckGMboxInterrupts(struct ar6k_device *pDev) +{ + int status = 0; + u8 counter_int_status; + int credits; + u8 host_int_status2; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n")); + + /* the caller guarantees that this is a context that allows for blocking I/O */ + + do { + + host_int_status2 = pDev->IrqProcRegisters.host_int_status2 & + pDev->GMboxControlRegisters.int_status_enable; + + if (host_int_status2 & GMBOX_INT_STATUS_TX_OVERFLOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : TX Overflow \n")); + status = A_ECOMM; + } + + if (host_int_status2 & GMBOX_INT_STATUS_RX_OVERFLOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : RX Overflow \n")); + status = A_ECOMM; + } + + if (status) { + if (pDev->GMboxInfo.pTargetFailureCallback != NULL) { + pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status); + } + break; + } + + if (host_int_status2 & GMBOX_INT_STATUS_RX_DATA) { + if (pDev->IrqProcRegisters.gmbox_rx_avail > 0) { + A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL); + status = pDev->GMboxInfo.pMessagePendingCallBack( + pDev->GMboxInfo.pProtocolContext, + (u8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0], + pDev->IrqProcRegisters.gmbox_rx_avail); + } + } + + if (status) { + break; + } + + counter_int_status = pDev->IrqProcRegisters.counter_int_status & + pDev->IrqEnableRegisters.counter_int_status_enable; + + /* check if credit interrupt is pending */ + if (counter_int_status & (COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER))) { + + /* do synchronous read */ + status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits); + + if (status) { + break; + } + + A_ASSERT(pDev->GMboxInfo.pCreditsPendingCallback != NULL); + status = pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext, + credits, + pDev->GMboxInfo.CreditCountIRQEnabled); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status)); + + return status; +} + + +int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength) +{ + u32 paddedLength; + bool sync = (pPacket->Completion == NULL) ? true : false; + int status; + u32 address; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("DevGMboxWrite, Padded Length: %d Mbox:0x%X (mode:%s)\n", + WriteLength, + pDev->MailBoxInfo.GMboxAddress, + sync ? "SYNC" : "ASYNC")); + + /* last byte of packet has to hit the EOM marker */ + address = pDev->MailBoxInfo.GMboxAddress + pDev->MailBoxInfo.GMboxSize - paddedLength; + + status = HIFReadWrite(pDev->HIFDevice, + address, + pPacket->pBuffer, + paddedLength, /* the padded length */ + sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + +int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength) +{ + + u32 paddedLength; + int status; + bool sync = (pPacket->Completion == NULL) ? true : false; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength); + + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", + paddedLength,ReadLength,pPacket->BufferLength)); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DevGMboxRead (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, + paddedLength, + pDev->MailBoxInfo.GMboxAddress, + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.GMboxAddress, + pPacket->pBuffer, + paddedLength, + sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } + + return status; +} + + +static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length) +{ + int credits = 0; + + /* theory of how this works: + * We read the credit decrement register multiple times on a byte-wide basis. + * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a + * reasonable chance to acquire "all" pending credits in a single I/O operation. + * + * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions. + * Each non-zero byte represents a single credit decrement (which is a credit given back to the host) + * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following + * pattern "could" appear: + * + * 0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros + * <---------> <-----------------------------> + * \_ credits aleady there \_ target adding 4 more credits + * + * The total available credits would be 7, since there are 7 non-zero bytes in the buffer. + * + * */ + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer"); + } + + while (Length) { + if (*pBuffer != 0) { + credits++; + } + Length--; + pBuffer++; + } + + return credits; +} + + +/* callback when our fetch to enable/disable completes */ +static void DevGMboxReadCreditsAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Read Credit Operation failed! status:%d \n", pPacket->Status)); + } else { + int credits = 0; + credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); + pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext, + credits, + pDev->GMboxInfo.CreditCountIRQEnabled); + + + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n")); +} + +int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC")); + + do { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE); + + if (AsyncMode) { + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler; + pIOPacket->pContext = pDev; + /* read registers asynchronously */ + HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_DEC_ADDRESS, + pIOPacket->pBuffer, + AR6K_REG_IO_BUFFER_SIZE, /* hit the register multiple times */ + HIF_RD_ASYNC_BYTE_FIX, + pIOPacket); + pIOPacket = NULL; + break; + } + + pIOPacket->Completion = NULL; + /* if we get here we are doing it synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_DEC_ADDRESS, + pIOPacket->pBuffer, + AR6K_REG_IO_BUFFER_SIZE, + HIF_RD_SYNC_BYTE_FIX, + NULL); + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" DevGMboxReadCreditCounter failed! status:%d \n", status)); + } + + if (pIOPacket != NULL) { + if (!status) { + /* sync mode processing */ + *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); + } + AR6KFreeIOPacket(pDev,pIOPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n", + AsyncMode ? "ASYNC" : "SYNC", status)); + + return status; +} + +int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize) +{ + int status; + u8 buffer[4]; + + status = HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_SIZE_ADDRESS, + buffer, + sizeof(buffer), + HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ + NULL); + + if (!status) { + if (buffer[0] == 0) { + *pCreditSize = 256; + } else { + *pCreditSize = buffer[0]; + } + + } + + return status; +} + +void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev) +{ + /* Target ASSERTED!!! */ + if (pDev->GMboxInfo.pTargetFailureCallback != NULL) { + pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, A_HARDWARE); + } +} + +int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes) +{ + + int status = 0; + struct ar6k_irq_proc_registers procRegs; + int maxCopy; + + do { + /* on entry the caller provides the length of the lookahead buffer */ + if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) { + A_ASSERT(false); + status = A_EINVAL; + break; + } + + maxCopy = *pLookAheadBytes; + *pLookAheadBytes = 0; + /* load the register table from the device */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&procRegs, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status)); + break; + } + + if (procRegs.gmbox_rx_avail > 0) { + int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail; + memcpy(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes); + *pLookAheadBytes = bytes; + } + + } while (false); + + return status; +} + +int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS) +{ + int status = 0; + int i; + u8 buffer[4]; + + A_MEMZERO(buffer, sizeof(buffer)); + + do { + + if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) { + status = A_EINVAL; + break; + } + + /* set the last buffer to do the actual signal trigger */ + buffer[3] = (1 << Signal); + + status = HIFReadWrite(pDev->HIFDevice, + INT_WLAN_ADDRESS, + buffer, + sizeof(buffer), + HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ + NULL); + + if (status) { + break; + } + + } while (false); + + + if (!status) { + /* now read back the register to see if the bit cleared */ + while (AckTimeoutMS) { + status = HIFReadWrite(pDev->HIFDevice, + INT_WLAN_ADDRESS, + buffer, + sizeof(buffer), + HIF_RD_SYNC_BYTE_FIX, + NULL); + + if (status) { + break; + } + + for (i = 0; i < sizeof(buffer); i++) { + if (buffer[i] & (1 << Signal)) { + /* bit is still set */ + break; + } + } + + if (i >= sizeof(buffer)) { + /* done */ + break; + } + + AckTimeoutMS--; + A_MDELAY(1); + } + + if (0 == AckTimeoutMS) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal)); + status = A_ERROR; + } + } + + return status; + +} + +#endif //ATH_AR6K_ENABLE_GMBOX + + + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c new file mode 100644 index 000000000000..56a0d7143804 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c @@ -0,0 +1,1284 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Protocol module for use in bridging HCI-UART packets over the GMBOX interface +// +// Author(s): ="Atheros" +//============================================================================== +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" +#include "hci_transport_api.h" +#include "gmboxif.h" +#include "ar6000_diag.h" +#include "hw/apb_map.h" +#include "hw/mbox_reg.h" + +#ifdef ATH_AR6K_ENABLE_GMBOX +#define HCI_UART_COMMAND_PKT 0x01 +#define HCI_UART_ACL_PKT 0x02 +#define HCI_UART_SCO_PKT 0x03 +#define HCI_UART_EVENT_PKT 0x04 + +#define HCI_RECV_WAIT_BUFFERS (1 << 0) + +#define HCI_SEND_WAIT_CREDITS (1 << 0) + +#define HCI_UART_BRIDGE_CREDIT_SIZE 128 + +#define CREDIT_POLL_COUNT 256 + +#define HCI_DELAY_PER_INTERVAL_MS 10 +#define BTON_TIMEOUT_MS 500 +#define BTOFF_TIMEOUT_MS 500 +#define BAUD_TIMEOUT_MS 1 +#define BTPWRSAV_TIMEOUT_MS 1 + +struct gmbox_proto_hci_uart { + struct hci_transport_config_info HCIConfig; + bool HCIAttached; + bool HCIStopped; + u32 RecvStateFlags; + u32 SendStateFlags; + HCI_TRANSPORT_PACKET_TYPE WaitBufferType; + struct htc_packet_queue SendQueue; /* write queue holding HCI Command and ACL packets */ + struct htc_packet_queue HCIACLRecvBuffers; /* recv queue holding buffers for incomming ACL packets */ + struct htc_packet_queue HCIEventBuffers; /* recv queue holding buffers for incomming event packets */ + struct ar6k_device *pDev; + A_MUTEX_T HCIRxLock; + A_MUTEX_T HCITxLock; + int CreditsMax; + int CreditsConsumed; + int CreditsAvailable; + int CreditSize; + int CreditsCurrentSeek; + int SendProcessCount; +}; + +#define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock); +#define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock); +#define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock); +#define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock); + +#define DO_HCI_RECV_INDICATION(p, pt) \ +do { \ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, \ + ("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \ + (unsigned long)(pt), \ + (pt)->Status, \ + !(pt)->Status ? (pt)->ActualLength : 0, \ + HCI_GET_PACKET_TYPE(pt))); \ + (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \ +} while (0) + +#define DO_HCI_SEND_INDICATION(p,pt) \ +{ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n", \ + (unsigned long)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \ + (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \ +} + +static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous); + +static void HCIUartCleanup(struct gmbox_proto_hci_uart *pProtocol) +{ + A_ASSERT(pProtocol != NULL); + + A_MUTEX_DELETE(&pProtocol->HCIRxLock); + A_MUTEX_DELETE(&pProtocol->HCITxLock); + + kfree(pProtocol); +} + +static int InitTxCreditState(struct gmbox_proto_hci_uart *pProt) +{ + int status; + int credits; + int creditPollCount = CREDIT_POLL_COUNT; + bool gotCredits = false; + + pProt->CreditsConsumed = 0; + + do { + + if (pProt->CreditsMax != 0) { + /* we can only call this only once per target reset */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called! \n")); + A_ASSERT(false); + status = A_EINVAL; + break; + } + + /* read the credit counter. At startup the target will set the credit counter + * to the max available, we read this in a loop because it may take + * multiple credit counter reads to get all credits */ + + while (creditPollCount) { + + credits = 0; + + status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits); + + if (status) { + break; + } + + if (!gotCredits && (0 == credits)) { + creditPollCount--; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount)); + A_MDELAY(HCI_DELAY_PER_INTERVAL_MS); + continue; + } else { + gotCredits = true; + } + + if (0 == credits) { + break; + } + + pProt->CreditsMax += credits; + } + + if (status) { + break; + } + + if (0 == creditPollCount) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("** HCI : Failed to get credits! GMBOX Target was not available \n")); + status = A_ERROR; + break; + } + + /* now get the size */ + status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize); + + if (status) { + break; + } + + } while (false); + + if (!status) { + pProt->CreditsAvailable = pProt->CreditsMax; + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n", + pProt->CreditsAvailable, pProt->CreditSize)); + } + + return status; +} + +static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQEnabled) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + bool enableCreditIrq = false; + bool disableCreditIrq = false; + bool doPendingSends = false; + int status = 0; + + /** this callback is called under 2 conditions: + * 1. The credit IRQ interrupt was enabled and signaled. + * 2. A credit counter read completed. + * + * The function must not assume that the calling context can block ! + */ + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ:%s) \n", + Credits, CreditIRQEnabled ? "ON" : "OFF")); + + LOCK_HCI_TX(pProt); + + do { + + if (0 == Credits) { + if (!CreditIRQEnabled) { + /* enable credit IRQ */ + enableCreditIrq = true; + } + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n", + pProt->CreditsConsumed, + pProt->CreditsAvailable, + pProt->CreditsMax, + pProt->CreditsCurrentSeek)); + + pProt->CreditsAvailable += Credits; + A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax); + pProt->CreditsConsumed -= Credits; + A_ASSERT(pProt->CreditsConsumed >= 0); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d available:%d max:%d seek:%d\n", + pProt->CreditsConsumed, + pProt->CreditsAvailable, + pProt->CreditsMax, + pProt->CreditsCurrentSeek)); + + if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) { + /* we have enough credits to fulfill at least 1 packet waiting in the queue */ + pProt->CreditsCurrentSeek = 0; + pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS; + doPendingSends = true; + if (CreditIRQEnabled) { + /* credit IRQ was enabled, we shouldn't need it anymore */ + disableCreditIrq = true; + } + } else { + /* not enough credits yet, enable credit IRQ if we haven't already */ + if (!CreditIRQEnabled) { + enableCreditIrq = true; + } + } + + } while (false); + + UNLOCK_HCI_TX(pProt); + + if (enableCreditIrq) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n")); + /* must use async only */ + status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO_ASYNC); + } else if (disableCreditIrq) { + /* must use async only */ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n")); + status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_IO_ASYNC); + } + + if (doPendingSends) { + HCITrySend(pProt, NULL, false); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n")); + return status; +} + +static INLINE void NotifyTransportFailure(struct gmbox_proto_hci_uart *pProt, int status) +{ + if (pProt->HCIConfig.TransportFailure != NULL) { + pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status); + } +} + +static void FailureCallback(void *pContext, int Status) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + + /* target assertion occurred */ + NotifyTransportFailure(pProt, Status); +} + +static void StateDumpCallback(void *pContext) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStateFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStateFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBufferType)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue))); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsMax)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsConsumed)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsAvailable)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n")); +} + +static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidBytes) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + int status = 0; + int totalRecvLength = 0; + HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID; + bool recvRefillCalled = false; + bool blockRecv = false; + struct htc_packet *pPacket = NULL; + + /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */ + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \n",ValidBytes)); + + LOCK_HCI_RX(pProt); + + do { + + if (ValidBytes < 3) { + /* not enough for ACL or event header */ + break; + } + + if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) { + /* not enough for ACL data header */ + break; + } + + switch (LookAheadBytes[0]) { + case HCI_UART_EVENT_PKT: + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n", + LookAheadBytes[1], LookAheadBytes[2])); + totalRecvLength = LookAheadBytes[2]; + totalRecvLength += 3; /* add type + event code + length field */ + pktType = HCI_EVENT_TYPE; + break; + case HCI_UART_ACL_PKT: + totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3]; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \n", + ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], totalRecvLength)); + totalRecvLength += 5; /* add type + connection handle + length field */ + pktType = HCI_ACL_TYPE; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",LookAheadBytes[0])); + status = A_EPROTO; + break; + } + + if (status) { + break; + } + + if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) { + UNLOCK_HCI_RX(pProt); + /* user is using a per-packet allocation callback */ + pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContext, + pktType, + totalRecvLength); + LOCK_HCI_RX(pProt); + + } else { + struct htc_packet_queue *pQueue; + /* user is using a refill handler that can refill multiple HTC buffers */ + + /* select buffer queue */ + if (pktType == HCI_ACL_TYPE) { + pQueue = &pProt->HCIACLRecvBuffers; + } else { + pQueue = &pProt->HCIEventBuffers; + } + + if (HTC_QUEUE_EMPTY(pQueue)) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d has no buffers available calling allocation handler \n", + pktType)); + /* check for refill handler */ + if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) { + recvRefillCalled = true; + UNLOCK_HCI_RX(pProt); + /* call the re-fill handler */ + pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext, + pktType, + 0); + LOCK_HCI_RX(pProt); + /* check if we have more buffers */ + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* fall through */ + } + } else { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HCI pkt type: %d now has %d recv buffers left \n", + pktType, HTC_PACKET_QUEUE_DEPTH(pQueue))); + } + } + + if (NULL == pPacket) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d has no buffers available stopping recv...\n", pktType)); + /* this is not an error, we simply need to mark that we are waiting for buffers.*/ + pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS; + pProt->WaitBufferType = pktType; + blockRecv = true; + break; + } + + if (totalRecvLength > (int)pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d bytes (%d buffer bytes avail) ! \n", + LookAheadBytes[0], totalRecvLength, pPacket->BufferLength)); + status = A_EINVAL; + break; + } + + } while (false); + + UNLOCK_HCI_RX(pProt); + + /* locks are released, we can go fetch the packet */ + + do { + + if (status || (NULL == pPacket)) { + break; + } + + /* do this synchronously, we don't need to be fast here */ + pPacket->Completion = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-uart-type: %s \n", + totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EVENT" : "ACL")); + + status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength); + + if (status) { + break; + } + + if (pPacket->pBuffer[0] != LookAheadBytes[0]) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expected packet type: %d ! \n", + pPacket->pBuffer[0])); + status = A_EPROTO; + break; + } + + if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) { + /* validate event header fields */ + if ((pPacket->pBuffer[1] != LookAheadBytes[1]) || + (pPacket->pBuffer[2] != LookAheadBytes[2])) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n")); + DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header"); + DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header"); + status = A_EPROTO; + break; + } + } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) { + /* validate acl header fields */ + if ((pPacket->pBuffer[1] != LookAheadBytes[1]) || + (pPacket->pBuffer[2] != LookAheadBytes[2]) || + (pPacket->pBuffer[3] != LookAheadBytes[3]) || + (pPacket->pBuffer[4] != LookAheadBytes[4])) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n")); + DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header"); + DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header"); + status = A_EPROTO; + break; + } + } + + /* adjust buffer to move past packet ID */ + pPacket->pBuffer++; + pPacket->ActualLength = totalRecvLength - 1; + pPacket->Status = 0; + /* indicate packet */ + DO_HCI_RECV_INDICATION(pProt,pPacket); + pPacket = NULL; + + /* check if we need to refill recv buffers */ + if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) { + struct htc_packet_queue *pQueue; + int watermark; + + if (pktType == HCI_ACL_TYPE) { + watermark = pProt->HCIConfig.ACLRecvBufferWaterMark; + pQueue = &pProt->HCIACLRecvBuffers; + } else { + watermark = pProt->HCIConfig.EventRecvBufferWaterMark; + pQueue = &pProt->HCIEventBuffers; + } + + if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d watermark hit (%d) current:%d \n", + pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue))); + /* call the re-fill handler */ + pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext, + pktType, + HTC_PACKET_QUEUE_DEPTH(pQueue)); + } + } + + } while (false); + + /* check if we need to disable the receiver */ + if (status || blockRecv) { + DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC); + } + + /* see if we need to recycle the recv buffer */ + if (status && (pPacket != NULL)) { + struct htc_packet_queue queue; + + if (A_EPROTO == status) { + DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet"); + } + /* recycle packet */ + HTC_PACKET_RESET_RX(pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + HCI_TransportAddReceivePkts(pProt,&queue); + NotifyTransportFailure(pProt,status); + } + + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n")); + + return status; +} + +static void HCISendPacketCompletion(void *Context, struct htc_packet *pPacket) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)Context; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n", + (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength)); + } + + DO_HCI_SEND_INDICATION(pProt,pPacket); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n")); +} + +static int SeekCreditsSynch(struct gmbox_proto_hci_uart *pProt) +{ + int status = 0; + int credits; + int retry = 100; + + while (true) { + credits = 0; + status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits); + if (status) { + break; + } + LOCK_HCI_TX(pProt); + pProt->CreditsAvailable += credits; + pProt->CreditsConsumed -= credits; + if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) { + pProt->CreditsCurrentSeek = 0; + UNLOCK_HCI_TX(pProt); + break; + } + UNLOCK_HCI_TX(pProt); + retry--; + if (0 == retry) { + status = A_EBUSY; + break; + } + A_MDELAY(20); + } + + return status; +} + +static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous) +{ + int status = 0; + int transferLength; + int creditsRequired, remainder; + u8 hciUartType; + bool synchSendComplete = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket, + Synchronous ? "SYNC" :"ASYNC")); + + LOCK_HCI_TX(pProt); + + /* increment write processing count on entry */ + pProt->SendProcessCount++; + + do { + + if (pProt->HCIStopped) { + status = A_ECANCELED; + break; + } + + if (pPacket != NULL) { + /* packet was supplied */ + if (Synchronous) { + /* in synchronous mode, the send queue can only hold 1 packet */ + if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + status = A_EBUSY; + A_ASSERT(false); + break; + } + + if (pProt->SendProcessCount > 1) { + /* another thread or task is draining the TX queues */ + status = A_EBUSY; + A_ASSERT(false); + break; + } + + HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket); + + } else { + /* see if adding this packet hits the max depth (asynchronous mode only) */ + if ((pProt->HCIConfig.MaxSendQueueDepth > 0) && + ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->HCIConfig.MaxSendQueueDepth)) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, Depth:%d, Max:%d \n", + HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue), + pProt->HCIConfig.MaxSendQueueDepth)); + /* queue will be full, invoke any callbacks to determine what action to take */ + if (pProt->HCIConfig.pHCISendFull != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("HCI : Calling driver's send full callback.... \n")); + if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pContext, + pPacket) == HCI_SEND_FULL_DROP) { + /* drop it */ + status = A_NO_RESOURCE; + break; + } + } + } + + HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket); + } + + } + + if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) { + break; + } + + if (pProt->SendProcessCount > 1) { + /* another thread or task is draining the TX queues */ + break; + } + + /***** beyond this point only 1 thread may enter ******/ + + /* now drain the send queue for transmission as long as we have enough + * credits */ + while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + + pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue); + + switch (HCI_GET_PACKET_TYPE(pPacket)) { + case HCI_COMMAND_TYPE: + hciUartType = HCI_UART_COMMAND_PKT; + break; + case HCI_ACL_TYPE: + hciUartType = HCI_UART_ACL_PKT; + break; + default: + status = A_EINVAL; + A_ASSERT(false); + break; + } + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%lX , Type:%d Length: %d Remaining Queue Depth: %d\n", + (unsigned long)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->ActualLength, + HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue))); + + transferLength = 1; /* UART type header is 1 byte */ + transferLength += pPacket->ActualLength; + transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLength); + + /* figure out how many credits this message requires */ + creditsRequired = transferLength / pProt->CreditSize; + remainder = transferLength % pProt->CreditSize; + + if (remainder) { + creditsRequired++; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n", + creditsRequired, pProt->CreditsAvailable)); + + if (creditsRequired > pProt->CreditsAvailable) { + if (Synchronous) { + /* in synchronous mode we need to seek credits in synchronously */ + pProt->CreditsCurrentSeek = creditsRequired; + UNLOCK_HCI_TX(pProt); + status = SeekCreditsSynch(pProt); + LOCK_HCI_TX(pProt); + if (status) { + break; + } + /* fall through and continue processing this send op */ + } else { + /* not enough credits, queue back to the head */ + HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket); + /* waiting for credits */ + pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS; + /* provide a hint to reduce attempts to re-send if credits are dribbling back + * this hint is the short fall of credits */ + pProt->CreditsCurrentSeek = creditsRequired; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%lX placed back in queue. head packet needs: %d credits \n", + (unsigned long)pPacket, pProt->CreditsCurrentSeek)); + pPacket = NULL; + UNLOCK_HCI_TX(pProt); + + /* schedule a credit counter read, our CreditsAvailableCallback callback will be called + * with the result */ + DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL); + + LOCK_HCI_TX(pProt); + break; + } + } + + /* caller guarantees some head room */ + pPacket->pBuffer--; + pPacket->pBuffer[0] = hciUartType; + + pProt->CreditsAvailable -= creditsRequired; + pProt->CreditsConsumed += creditsRequired; + A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n", + pProt->CreditsConsumed, pProt->CreditsAvailable, pProt->CreditsMax)); + + UNLOCK_HCI_TX(pProt); + + /* write it out */ + if (Synchronous) { + pPacket->Completion = NULL; + pPacket->pContext = NULL; + } else { + pPacket->Completion = HCISendPacketCompletion; + pPacket->pContext = pProt; + } + + status = DevGMboxWrite(pProt->pDev,pPacket,transferLength); + if (Synchronous) { + synchSendComplete = true; + } else { + pPacket = NULL; + } + + LOCK_HCI_TX(pProt); + + } + + } while (false); + + pProt->SendProcessCount--; + A_ASSERT(pProt->SendProcessCount >= 0); + UNLOCK_HCI_TX(pProt); + + if (Synchronous) { + A_ASSERT(pPacket != NULL); + if (!status && (!synchSendComplete)) { + status = A_EBUSY; + A_ASSERT(false); + LOCK_HCI_TX(pProt); + if (pPacket->ListLink.pNext != NULL) { + /* remove from the queue */ + HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket); + } + UNLOCK_HCI_TX(pProt); + } + } else { + if (status && (pPacket != NULL)) { + pPacket->Status = status; + DO_HCI_SEND_INDICATION(pProt,pPacket); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n")); + return status; +} + +static void FlushSendQueue(struct gmbox_proto_hci_uart *pProt) +{ + struct htc_packet *pPacket; + struct htc_packet_queue discardQueue; + + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HCI_TX(pProt); + + if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue); + } + + UNLOCK_HCI_TX(pProt); + + /* discard packets */ + while (!HTC_QUEUE_EMPTY(&discardQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_SEND_INDICATION(pProt,pPacket); + } + +} + +static void FlushRecvBuffers(struct gmbox_proto_hci_uart *pProt) +{ + struct htc_packet_queue discardQueue; + struct htc_packet *pPacket; + + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HCI_RX(pProt); + /*transfer list items from ACL and event buffer queues to the discard queue */ + if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffers); + } + if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers); + } + UNLOCK_HCI_RX(pProt); + + /* now empty the discard queue */ + while (!HTC_QUEUE_EMPTY(&discardQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_RECV_INDICATION(pProt,pPacket); + } + +} + +/*** protocol module install entry point ***/ + +int GMboxProtocolInstall(struct ar6k_device *pDev) +{ + int status = 0; + struct gmbox_proto_hci_uart *pProtocol = NULL; + + do { + + pProtocol = A_MALLOC(sizeof(struct gmbox_proto_hci_uart)); + + if (NULL == pProtocol) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pProtocol, sizeof(*pProtocol)); + pProtocol->pDev = pDev; + INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue); + INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers); + INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers); + A_MUTEX_INIT(&pProtocol->HCIRxLock); + A_MUTEX_INIT(&pProtocol->HCITxLock); + + } while (false); + + if (!status) { + LOCK_AR6K(pDev); + DEV_GMBOX_SET_PROTOCOL(pDev, + HCIUartMessagePending, + CreditsAvailableCallback, + FailureCallback, + StateDumpCallback, + pProtocol); + UNLOCK_AR6K(pDev); + } else { + if (pProtocol != NULL) { + HCIUartCleanup(pProtocol); + } + } + + return status; +} + +/*** protocol module uninstall entry point ***/ +void GMboxProtocolUninstall(struct ar6k_device *pDev) +{ + struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev); + + if (pProtocol != NULL) { + + /* notify anyone attached */ + if (pProtocol->HCIAttached) { + A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL); + pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext); + pProtocol->HCIAttached = false; + } + + HCIUartCleanup(pProtocol); + DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL); + } + +} + +static int NotifyTransportReady(struct gmbox_proto_hci_uart *pProt) +{ + struct hci_transport_properties props; + int status = 0; + + do { + + A_MEMZERO(&props,sizeof(props)); + + /* HCI UART only needs one extra byte at the head to indicate the packet TYPE */ + props.HeadRoom = 1; + props.TailRoom = 0; + props.IOBlockPad = pProt->pDev->BlockSize; + if (pProt->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to transport... \n")); + A_ASSERT(pProt->HCIConfig.TransportReady != NULL); + status = pProt->HCIConfig.TransportReady(pProt, + &props, + pProt->HCIConfig.pContext); + } + + } while (false); + + return status; +} + +/*********** HCI UART protocol implementation ************************************************/ + +HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo) +{ + struct gmbox_proto_hci_uart *pProtocol = NULL; + struct ar6k_device *pDev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n")); + + pDev = HTCGetAR6KDevice(HTCHandle); + + LOCK_AR6K(pDev); + + do { + + pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev); + + if (NULL == pProtocol) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n")); + break; + } + + if (pProtocol->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n")); + break; + } + + memcpy(&pProtocol->HCIConfig, pInfo, sizeof(struct hci_transport_config_info)); + + A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL); + A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL); + + pProtocol->HCIAttached = true; + + } while (false); + + UNLOCK_AR6K(pDev); + + if (pProtocol != NULL) { + /* TODO ... should we use a worker? */ + NotifyTransportReady(pProtocol); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%lX) \n",(unsigned long)pProtocol)); + return (HCI_TRANSPORT_HANDLE)pProtocol; +} + +void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans) +{ + struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)HciTrans; + struct ar6k_device *pDev = pProtocol->pDev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n")); + + LOCK_AR6K(pDev); + if (!pProtocol->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n")); + UNLOCK_AR6K(pDev); + return; + } + pProtocol->HCIAttached = false; + UNLOCK_AR6K(pDev); + + HCI_TransportStop(HciTrans); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n")); +} + +int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + int status = 0; + bool unblockRecv = false; + struct htc_packet *pPacket; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n")); + + LOCK_HCI_RX(pProt); + + do { + + if (pProt->HCIStopped) { + status = A_ECANCELED; + break; + } + + pPacket = HTC_GET_PKT_AT_HEAD(pQueue); + + if (NULL == pPacket) { + status = A_EINVAL; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:%d num:%d \n", + HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC_PACKET_QUEUE_DEPTH(pQueue))); + + if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue); + } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue); + } else { + status = A_EINVAL; + break; + } + + if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) { + if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n", + pProt->WaitBufferType)); + pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS; + pProt->WaitBufferType = HCI_PACKET_INVALID; + unblockRecv = true; + } + } + + } while (false); + + UNLOCK_HCI_RX(pProt); + + if (status) { + while (!HTC_QUEUE_EMPTY(pQueue)) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_RECV_INDICATION(pProt,pPacket); + } + } + + if (unblockRecv) { + DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n")); + + return 0; +} + +int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + return HCITrySend(pProt,pPacket,Synchronous); +} + +void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n")); + + LOCK_AR6K(pProt->pDev); + if (pProt->HCIStopped) { + UNLOCK_AR6K(pProt->pDev); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n")); + return; + } + pProt->HCIStopped = true; + UNLOCK_AR6K(pProt->pDev); + + /* disable interrupts */ + DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC); + FlushSendQueue(pProt); + FlushRecvBuffers(pProt); + + /* signal bridge side to power down BT */ + DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TIMEOUT_MS); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n")); +} + +int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans) +{ + int status; + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n")); + + /* set stopped in case we have a problem in starting */ + pProt->HCIStopped = true; + + do { + + status = InitTxCreditState(pProt); + + if (status) { + break; + } + + status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC); + + if (status) { + break; + } + /* enable recv */ + status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC); + + if (status) { + break; + } + /* signal bridge side to power up BT */ + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n")); + break; + } + + /* we made it */ + pProt->HCIStopped = false; + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n")); + + return status; +} + +int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + return DevGMboxIRQAction(pProt->pDev, + Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE, + PROC_IO_SYNC); + +} + +int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + int status = 0; + u8 lookAhead[8]; + int bytes; + int totalRecvLength; + + MaxPollMS = MaxPollMS / 16; + + if (MaxPollMS < 2) { + MaxPollMS = 2; + } + + while (MaxPollMS) { + + bytes = sizeof(lookAhead); + status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes); + if (status) { + break; + } + + if (bytes < 3) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n", + bytes, MaxPollMS)); + A_MDELAY(16); + MaxPollMS--; + continue; + } + + totalRecvLength = 0; + switch (lookAhead[0]) { + case HCI_UART_EVENT_PKT: + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n", + lookAhead[1], lookAhead[2])); + totalRecvLength = lookAhead[2]; + totalRecvLength += 3; /* add type + event code + length field */ + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",lookAhead[0])); + status = A_EPROTO; + break; + } + + if (status) { + break; + } + + pPacket->Completion = NULL; + status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength); + if (status) { + break; + } + + pPacket->pBuffer++; + pPacket->ActualLength = totalRecvLength - 1; + pPacket->Status = 0; + break; + } + + if (MaxPollMS == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n")); + status = A_ERROR; + } + + return status; +} + +#define LSB_SCRATCH_IDX 4 +#define MSB_SCRATCH_IDX 5 +int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + struct hif_device *pHIFDevice = (struct hif_device *)(pProt->pDev->HIFDevice); + u32 scaledBaud, scratchAddr; + int status = 0; + + /* Divide the desired baud rate by 100 + * Store the LSB in the local scratch register 4 and the MSB in the local + * scratch register 5 for the target to read + */ + scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * LSB_SCRATCH_IDX); + scaledBaud = (Baud / 100) & LOCAL_SCRATCH_VALUE_MASK; + status = ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud); + scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX); + scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK; + status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!")); + return status; + } + + /* Now interrupt the target to tell it about the baud rate */ + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!")); + } + + return status; +} + +int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable) +{ + int status; + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + if (Enable) { + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS); + } else { + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n")); + } + + return status; +} + +#endif //ATH_AR6K_ENABLE_GMBOX + diff --git a/trunk/drivers/staging/ath6kl/htc2/htc.c b/trunk/drivers/staging/ath6kl/htc2/htc.c new file mode 100644 index 000000000000..ae54e64b6243 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc.c @@ -0,0 +1,575 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +#ifdef ATH_DEBUG_MODULE +static struct ath_debug_mask_description g_HTCDebugDescription[] = { + { ATH_DEBUG_SEND , "Send"}, + { ATH_DEBUG_RECV , "Recv"}, + { ATH_DEBUG_SYNC , "Sync"}, + { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"}, + { ATH_DEBUG_IRQ , "Interrupt Processing"} +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, + "htc", + "Host Target Communications", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription), + g_HTCDebugDescription); + +#endif + +static void HTCReportFailure(void *Context); +static void ResetEndpointStates(struct htc_target *target); + +void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList) +{ + LOCK_HTC(target); + HTC_PACKET_ENQUEUE(pList,pPacket); + UNLOCK_HTC(target); +} + +struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList) +{ + struct htc_packet *pPacket; + + LOCK_HTC(target); + pPacket = HTC_PACKET_DEQUEUE(pList); + UNLOCK_HTC(target); + + return pPacket; +} + +/* cleanup the HTC instance */ +static void HTCCleanup(struct htc_target *target) +{ + s32 i; + + DevCleanup(&target->Device); + + for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { + if (target->HTCControlBuffers[i].Buffer) { + kfree(target->HTCControlBuffers[i].Buffer); + } + } + + if (A_IS_MUTEX_VALID(&target->HTCLock)) { + A_MUTEX_DELETE(&target->HTCLock); + } + + if (A_IS_MUTEX_VALID(&target->HTCRxLock)) { + A_MUTEX_DELETE(&target->HTCRxLock); + } + + if (A_IS_MUTEX_VALID(&target->HTCTxLock)) { + A_MUTEX_DELETE(&target->HTCTxLock); + } + /* free our instance */ + kfree(target); +} + +/* registered target arrival callback from the HIF layer */ +HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo) +{ + struct htc_target *target = NULL; + int status = 0; + int i; + u32 ctrl_bufsz; + u32 blocksizes[HTC_MAILBOX_NUM_MAX]; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n")); + + A_REGISTER_MODULE_DEBUG_INFO(htc); + + do { + + /* allocate target memory */ + if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); + status = A_ERROR; + break; + } + + A_MEMZERO(target, sizeof(struct htc_target)); + A_MUTEX_INIT(&target->HTCLock); + A_MUTEX_INIT(&target->HTCRxLock); + A_MUTEX_INIT(&target->HTCTxLock); + INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); + INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList); + + /* give device layer the hif device handle */ + target->Device.HIFDevice = hif_handle; + /* give the device layer our context (for event processing) + * the device layer will register it's own context with HIF + * so we need to set this so we can fetch it in the target remove handler */ + target->Device.HTCContext = target; + /* set device layer target failure callback */ + target->Device.TargetFailureCallback = HTCReportFailure; + /* set device layer recv message pending callback */ + target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler; + target->EpWaitingForBuffers = ENDPOINT_MAX; + + memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info)); + + ResetEndpointStates(target); + + /* setup device layer */ + status = DevSetup(&target->Device); + + if (status) { + break; + } + + + /* get the block sizes */ + status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n")); + break; + } + + /* Set the control buffer size based on the block size */ + if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) { + ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH; + } else { + ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH; + } + for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { + target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz); + if (target->HTCControlBuffers[i].Buffer == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); + status = A_ERROR; + break; + } + } + + if (status) { + break; + } + + /* carve up buffers/packets for control messages */ + for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) { + struct htc_packet *pControlPacket; + pControlPacket = &target->HTCControlBuffers[i].HtcPacket; + SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket, + target, + target->HTCControlBuffers[i].Buffer, + ctrl_bufsz, + ENDPOINT_0); + HTC_FREE_CONTROL_RX(target,pControlPacket); + } + + for (;i < NUM_CONTROL_BUFFERS;i++) { + struct htc_packet *pControlPacket; + pControlPacket = &target->HTCControlBuffers[i].HtcPacket; + INIT_HTC_PACKET_INFO(pControlPacket, + target->HTCControlBuffers[i].Buffer, + ctrl_bufsz); + HTC_FREE_CONTROL_TX(target,pControlPacket); + } + + } while (false); + + if (status) { + if (target != NULL) { + HTCCleanup(target); + target = NULL; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n")); + + return target; +} + +void HTCDestroy(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%lX \n",(unsigned long)target)); + HTCCleanup(target); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n")); +} + +/* get the low level HIF device for the caller , the caller may wish to do low level + * HIF requests */ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return target->Device.HIFDevice; +} + +/* wait for the target to arrive (sends HTC Ready message) + * this operation is fully synchronous and the message is polled for */ +int HTCWaitTarget(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int status; + struct htc_packet *pPacket = NULL; + HTC_READY_EX_MSG *pRdyMsg; + + struct htc_service_connect_req connect; + struct htc_service_connect_resp resp; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target)); + + do { + +#ifdef MBOXHW_UNIT_TEST + + status = DoMboxHWTest(&target->Device); + + if (status) { + break; + } + +#endif + + /* we should be getting 1 control message that the target is ready */ + status = HTCWaitforControlMessage(target, &pPacket); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n")); + break; + } + + /* we controlled the buffer creation so it has to be properly aligned */ + pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer; + + if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) || + (pPacket->ActualLength < sizeof(HTC_READY_MSG))) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + + if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount; + target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size: %d\n", + target->TargetCredits, target->TargetCreditSize)); + + /* check if this is an extended ready message */ + if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) { + /* this is an extended message */ + target->HTCTargetVersion = pRdyMsg->HTCVersion; + target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle; + } else { + /* legacy */ + target->HTCTargetVersion = HTC_VERSION_2P0; + target->MaxMsgPerBundle = 0; + } + +#ifdef HTC_FORCE_LEGACY_2P0 + /* for testing and comparison...*/ + target->HTCTargetVersion = HTC_VERSION_2P0; + target->MaxMsgPerBundle = 0; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("Using HTC Protocol Version : %s (%d)\n ", + (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", + target->HTCTargetVersion)); + + if (target->MaxMsgPerBundle > 0) { + /* limit what HTC can handle */ + target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle); + /* target supports message bundling, setup device layer */ + if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) { + /* device layer can't handle bundling */ + target->MaxMsgPerBundle = 0; + } else { + /* limit bundle what the device layer can handle */ + target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target->Device), + target->MaxMsgPerBundle); + } + } + + if (target->MaxMsgPerBundle > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle)); + + if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) { + target->SendBundlingEnabled = true; + } + if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) { + target->RecvBundlingEnabled = true; + } + + if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not block aligned! Disabling send bundling \n", + target->TargetCreditSize)); + /* disallow send bundling since the credit size is not aligned to a block size + * the I/O block padding will spill into the next credit buffer which is fatal */ + target->SendBundlingEnabled = false; + } + } + + /* setup our pseudo HTC control endpoint connection */ + A_MEMZERO(&connect,sizeof(connect)); + A_MEMZERO(&resp,sizeof(resp)); + connect.EpCallbacks.pContext = target; + connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; + connect.EpCallbacks.EpRecv = HTCControlRecv; + connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */ + connect.EpCallbacks.EpSendFull = NULL; /* not nedded */ + connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS; + connect.ServiceID = HTC_CTRL_RSVD_SVC; + + /* connect fake service */ + status = HTCConnectService((HTC_HANDLE)target, + &connect, + &resp); + + if (!status) { + break; + } + + } while (false); + + if (pPacket != NULL) { + HTC_FREE_CONTROL_RX(target,pPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); + + return status; +} + + + +/* Start HTC, enable interrupts and let the target know host has finished setup */ +int HTCStart(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_packet *pPacket; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); + + /* make sure interrupts are disabled at the chip level, + * this function can be called again from a reboot of the target without shutting down HTC */ + DevDisableInterrupts(&target->Device); + /* make sure state is cleared again */ + target->OpStateFlags = 0; + target->RecvStateFlags = 0; + + /* now that we are starting, push control receive buffers into the + * HTC control endpoint */ + + while (1) { + pPacket = HTC_ALLOC_CONTROL_RX(target); + if (NULL == pPacket) { + break; + } + HTCAddReceivePkt((HTC_HANDLE)target,pPacket); + } + + do { + + AR_DEBUG_ASSERT(target->InitCredits != NULL); + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL); + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL); + + /* call init credits callback to do the distribution , + * NOTE: the first entry in the distribution list is ENDPOINT_0, so + * we pass the start of the list after this one. */ + target->InitCredits(target->pCredDistContext, + target->EpCreditDistributionListHead->pNext, + target->TargetCredits); + +#ifdef ATH_DEBUG_MODULE + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { + DumpCreditDistStates(target); + } +#endif + + /* the caller is done connecting to services, so we can indicate to the + * target that the setup phase is complete */ + status = HTCSendSetupComplete(target); + + if (status) { + break; + } + + /* unmask interrupts */ + status = DevUnmaskInterrupts(&target->Device); + + if (status) { + HTCStop(target); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); + return status; +} + +static void ResetEndpointStates(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + + A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist)); + pEndpoint->ServiceID = 0; + pEndpoint->MaxMsgLength = 0; + pEndpoint->MaxTxQueueDepth = 0; + A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats)); + INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers); + INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); + INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue); + pEndpoint->target = target; + } + /* reset distribution list */ + target->EpCreditDistributionListHead = NULL; +} + +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ +void HTCStop(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); + + LOCK_HTC(target); + /* mark that we are shutting down .. */ + target->OpStateFlags |= HTC_OP_STATE_STOPPING; + UNLOCK_HTC(target); + + /* Masking interrupts is a synchronous operation, when this function returns + * all pending HIF I/O has completed, we can safely flush the queues */ + DevMaskInterrupts(&target->Device); + +#ifdef THREAD_X + // + // Is this delay required + // + A_MDELAY(200); // wait for IRQ process done +#endif + /* flush all send packets */ + HTCFlushSendPkts(target); + /* flush all recv buffers */ + HTCFlushRecvBuffers(target); + + DevCleanupMsgBundling(&target->Device); + + ResetEndpointStates(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); +} + +#ifdef ATH_DEBUG_MODULE +void HTCDumpCreditStates(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + LOCK_HTC_TX(target); + + DumpCreditDistStates(target); + + UNLOCK_HTC_TX(target); + + DumpAR6KDevState(&target->Device); +} +#endif +/* report a target failure from the device, this is a callback from the device layer + * which uses a mechanism to report errors from the target (i.e. special interrupts) */ +static void HTCReportFailure(void *Context) +{ + struct htc_target *target = (struct htc_target *)Context; + + target->TargetFailure = true; + + if (target->HTCInitInfo.TargetFailure != NULL) { + /* let upper layer know, it needs to call HTCStop() */ + target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR); + } +} + +bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + struct htc_endpoint_stats *pStats) +{ + + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + bool clearStats = false; + bool sample = false; + + switch (Action) { + case HTC_EP_STAT_SAMPLE : + sample = true; + break; + case HTC_EP_STAT_SAMPLE_AND_CLEAR : + sample = true; + clearStats = true; + break; + case HTC_EP_STAT_CLEAR : + clearStats = true; + break; + default: + break; + } + + A_ASSERT(Endpoint < ENDPOINT_MAX); + + /* lock out TX and RX while we sample and/or clear */ + LOCK_HTC_TX(target); + LOCK_HTC_RX(target); + + if (sample) { + A_ASSERT(pStats != NULL); + /* return the stats to the caller */ + memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats)); + } + + if (clearStats) { + /* reset stats */ + A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats)); + } + + UNLOCK_HTC_RX(target); + UNLOCK_HTC_TX(target); + + return true; +} + +struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return &target->Device; +} + diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_debug.h b/trunk/drivers/staging/ath6kl/htc2/htc_debug.h new file mode 100644 index 000000000000..8455703e221c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_debug.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef HTC_DEBUG_H_ +#define HTC_DEBUG_H_ + +#define ATH_MODULE_NAME htc +#include "a_debug.h" + +/* ------- Debug related stuff ------- */ + +#define ATH_DEBUG_SEND ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_SYNC ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_DUMP ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_IRQ ATH_DEBUG_MAKE_MODULE_MASK(4) + + +#endif /*HTC_DEBUG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_internal.h b/trunk/drivers/staging/ath6kl/htc2/htc_internal.h new file mode 100644 index 000000000000..cac97351769a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_internal.h @@ -0,0 +1,211 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HTC_INTERNAL_H_ +#define _HTC_INTERNAL_H_ + +/* for debugging, uncomment this to capture the last frame header, on frame header + * processing errors, the last frame header is dump for comparison */ +//#define HTC_CAPTURE_LAST_FRAME + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "htc_debug.h" +#include "htc.h" +#include "htc_api.h" +#include "bmi_msg.h" +#include "hif.h" +#include "AR6000/ar6k.h" + +/* HTC operational parameters */ +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ +#define HTC_TARGET_DEBUG_INTR_MASK 0x01 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 + +#define HTC_HOST_MAX_MSG_PER_BUNDLE 8 +#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2 + +/* packet flags */ + +#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0) +#define HTC_RX_PKT_REFRESH_HDR (1 << 1) +#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2) +#define HTC_RX_PKT_NO_RECYCLE (1 << 3) + +/* scatter request flags */ + +#define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE (1 << 0) + +struct htc_endpoint { + HTC_ENDPOINT_ID Id; + HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to + non-zero value means this endpoint is in use */ + struct htc_packet_queue TxQueue; /* HTC frame buffer TX queue */ + struct htc_packet_queue RxBuffers; /* HTC frame buffer RX list */ + struct htc_endpoint_credit_dist CreditDist; /* credit distribution structure (exposed to driver layer) */ + struct htc_ep_callbacks EpCallBacks; /* callbacks associated with this endpoint */ + int MaxTxQueueDepth; /* max depth of the TX queue before we need to + call driver's full handler */ + int MaxMsgLength; /* max length of endpoint message */ + int TxProcessCount; /* reference count to continue tx processing */ + struct htc_packet_queue RecvIndicationQueue; /* recv packets ready to be indicated */ + int RxProcessCount; /* reference count to allow single processing context */ + struct htc_target *target; /* back pointer to target */ + u8 SeqNo; /* TX seq no (helpful) for debugging */ + u32 LocalConnectionFlags; /* local connection flags */ + struct htc_endpoint_stats EndPointStats; /* endpoint statistics */ +}; + +#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count); +#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL + +#define NUM_CONTROL_BUFFERS 8 +#define NUM_CONTROL_TX_BUFFERS 2 +#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS) + +struct htc_control_buffer { + struct htc_packet HtcPacket; + u8 *Buffer; +}; + +#define HTC_RECV_WAIT_BUFFERS (1 << 0) +#define HTC_OP_STATE_STOPPING (1 << 0) + +/* our HTC target state */ +struct htc_target { + struct htc_endpoint EndPoint[ENDPOINT_MAX]; + struct htc_control_buffer HTCControlBuffers[NUM_CONTROL_BUFFERS]; + struct htc_endpoint_credit_dist *EpCreditDistributionListHead; + struct htc_packet_queue ControlBufferTXFreeList; + struct htc_packet_queue ControlBufferRXFreeList; + HTC_CREDIT_DIST_CALLBACK DistributeCredits; + HTC_CREDIT_INIT_CALLBACK InitCredits; + void *pCredDistContext; + int TargetCredits; + unsigned int TargetCreditSize; + A_MUTEX_T HTCLock; + A_MUTEX_T HTCRxLock; + A_MUTEX_T HTCTxLock; + struct ar6k_device Device; /* AR6K - specific state */ + u32 OpStateFlags; + u32 RecvStateFlags; + HTC_ENDPOINT_ID EpWaitingForBuffers; + bool TargetFailure; +#ifdef HTC_CAPTURE_LAST_FRAME + struct htc_frame_hdr LastFrameHdr; /* useful for debugging */ + u8 LastTrailer[256]; + u8 LastTrailerLength; +#endif + struct htc_init_info HTCInitInfo; + u8 HTCTargetVersion; + int MaxMsgPerBundle; /* max messages per bundle for HTC */ + bool SendBundlingEnabled; /* run time enable for send bundling (dynamic) */ + int RecvBundlingEnabled; /* run time enable for recv bundling (dynamic) */ +}; + +#define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING) +#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock); +#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock); +#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock); +#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock); +#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock); +#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock); + +#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((struct htc_target *)(hnd)) +#define HTC_RECYCLE_RX_PKT(target,p,e) \ +{ \ + if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) { \ + HTC_PACKET_RESET_RX(pPacket); \ + pPacket->Status = A_ECANCELED; \ + (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \ + (p)); \ + } else { \ + HTC_PACKET_RESET_RX(pPacket); \ + HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \ + } \ +} + +/* internal HTC functions */ +void HTCControlTxComplete(void *Context, struct htc_packet *pPacket); +void HTCControlRecv(void *Context, struct htc_packet *pPacket); +int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket); +struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList); +void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList); +int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket); +void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket); +int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched); +void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint); +int HTCSendSetupComplete(struct htc_target *target); +void HTCFlushRecvBuffers(struct htc_target *target); +void HTCFlushSendPkts(struct htc_target *target); + +#ifdef ATH_DEBUG_MODULE +void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist); +void DumpCreditDistStates(struct htc_target *target); +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription); +#endif + +static INLINE struct htc_packet *HTC_ALLOC_CONTROL_TX(struct htc_target *target) { + struct htc_packet *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList); + if (pPacket != NULL) { + /* set payload pointer area with some headroom */ + pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH; + } + return pPacket; +} + +#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList) +#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList) +#define HTC_FREE_CONTROL_RX(t,p) \ +{ \ + HTC_PACKET_RESET_RX(p); \ + HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \ +} + +#define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1) \ +{ \ + u8 *pHdrBuf; \ + (pP)->pBuffer -= HTC_HDR_LENGTH; \ + pHdrBuf = (pP)->pBuffer; \ + A_SET_UINT16_FIELD(pHdrBuf,struct htc_frame_hdr,PayloadLen,(u16)(pP)->ActualLength); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,Flags,(sendflags)); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,EndpointID, (u8)(pP)->Endpoint); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[0], (u8)(ctrl0)); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[1], (u8)(ctrl1)); \ +} + +#define HTC_UNPREPARE_SEND_PKT(pP) \ + (pP)->pBuffer += HTC_HDR_LENGTH; \ + +#ifdef __cplusplus +} +#endif + +#endif /* _HTC_INTERNAL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_recv.c b/trunk/drivers/staging/ath6kl/htc2/htc_recv.c new file mode 100644 index 000000000000..974cc8cd6936 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_recv.c @@ -0,0 +1,1572 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +#define HTCIssueRecv(t, p) \ + DevRecvPacket(&(t)->Device, \ + (p), \ + (p)->ActualLength) + +#define DO_RCV_COMPLETION(e,q) DoRecvCompletion(e,q) + +#define DUMP_RECV_PKT_INFO(pP) \ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC RECV packet 0x%lX (%d bytes) (hdr:0x%X) on ep : %d \n", \ + (unsigned long)(pP), \ + (pP)->ActualLength, \ + (pP)->PktInfo.AsRx.ExpectedHdr, \ + (pP)->Endpoint)) + +#define HTC_RX_STAT_PROFILE(t,ep,numLookAheads) \ +{ \ + INC_HTC_EP_STAT((ep), RxReceived, 1); \ + if ((numLookAheads) == 1) { \ + INC_HTC_EP_STAT((ep), RxLookAheads, 1); \ + } else if ((numLookAheads) > 1) { \ + INC_HTC_EP_STAT((ep), RxBundleLookAheads, 1); \ + } \ +} + +static void DoRecvCompletion(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueueToIndicate) +{ + + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a recv multiple handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + struct htc_packet *pPacket; + /* using legacy EpRecv */ + do { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet 0x%lX \n", \ + pEndpoint->Id, (unsigned long)(pPacket))); + pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); + } while (!HTC_QUEUE_EMPTY(pQueueToIndicate)); + } + + } while (false); + +} + +static INLINE int HTCProcessTrailer(struct htc_target *target, + u8 *pBuffer, + int Length, + u32 *pNextLookAheads, + int *pNumLookAheads, + HTC_ENDPOINT_ID FromEndpoint) +{ + HTC_RECORD_HDR *pRecord; + u8 *pRecordBuf; + HTC_LOOKAHEAD_REPORT *pLookAhead; + u8 *pOrigBuffer; + int origLength; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length)); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); + } + + pOrigBuffer = pBuffer; + origLength = Length; + status = 0; + + while (Length > 0) { + + if (Length < sizeof(HTC_RECORD_HDR)) { + status = A_EPROTO; + break; + } + /* these are byte aligned structs */ + pRecord = (HTC_RECORD_HDR *)pBuffer; + Length -= sizeof(HTC_RECORD_HDR); + pBuffer += sizeof(HTC_RECORD_HDR); + + if (pRecord->Length > Length) { + /* no room left in buffer for record */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", + pRecord->Length, pRecord->RecordID, Length)); + status = A_EPROTO; + break; + } + /* start of record follows the header */ + pRecordBuf = pBuffer; + + switch (pRecord->RecordID) { + case HTC_RECORD_CREDITS: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT)); + HTCProcessCreditRpt(target, + (HTC_CREDIT_REPORT *)pRecordBuf, + pRecord->Length / (sizeof(HTC_CREDIT_REPORT)), + FromEndpoint); + break; + case HTC_RECORD_LOOKAHEAD: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT)); + pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf; + if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) && + (pNextLookAheads != NULL)) { + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n", + pLookAhead->PreValid, + pLookAhead->PostValid)); + + /* look ahead bytes are valid, copy them over */ + ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0]; + ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1]; + ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2]; + ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3]; + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead"); + } +#endif + /* just one normal lookahead */ + *pNumLookAheads = 1; + } + break; + case HTC_RECORD_LOOKAHEAD_BUNDLE: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)); + if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) && + (pNextLookAheads != NULL)) { + HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt; + int i; + + pBundledLookAheadRpt = (HTC_BUNDLED_LOOKAHEAD_REPORT *)pRecordBuf; + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes(pRecordBuf,pRecord->Length,"Bundle LookAhead"); + } +#endif + + if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) > + HTC_HOST_MAX_MSG_PER_BUNDLE) { + /* this should never happen, the target restricts the number + * of messages per bundle configured by the host */ + A_ASSERT(false); + status = A_EPROTO; + break; + } + + for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) { + ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0]; + ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1]; + ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2]; + ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3]; + pBundledLookAheadRpt++; + } + + *pNumLookAheads = i; + } + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n", + pRecord->RecordID, pRecord->Length)); + break; + } + + if (status) { + break; + } + + /* advance buffer past this record for next time around */ + pBuffer += pRecord->Length; + Length -= pRecord->Length; + } + +#ifdef ATH_DEBUG_MODULE + if (status) { + DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer"); + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); + return status; + +} + +/* process a received message (i.e. strip off header, process any trailer data) + * note : locks must be released when this function is called */ +static int HTCProcessRecvHeader(struct htc_target *target, + struct htc_packet *pPacket, + u32 *pNextLookAheads, + int *pNumLookAheads) +{ + u8 temp; + u8 *pBuf; + int status = 0; + u16 payloadLen; + u32 lookAhead; + + pBuf = pPacket->pBuffer; + + if (pNumLookAheads != NULL) { + *pNumLookAheads = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n")); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT"); + } + + do { + /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to + * retrieve 16 bit fields */ + payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen); + + ((u8 *)&lookAhead)[0] = pBuf[0]; + ((u8 *)&lookAhead)[1] = pBuf[1]; + ((u8 *)&lookAhead)[2] = pBuf[2]; + ((u8 *)&lookAhead)[3] = pBuf[3]; + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) { + /* refresh expected hdr, since this was unknown at the time we grabbed the packets + * as part of a bundle */ + pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead; + /* refresh actual length since we now have the real header */ + pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH; + + /* validate the actual header that was refreshed */ + if (pPacket->ActualLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n", + payloadLen, lookAhead)); + /* limit this to max buffer just to print out some of the buffer */ + pPacket->ActualLength = min(pPacket->ActualLength, pPacket->BufferLength); + status = A_EPROTO; + break; + } + + if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n", + A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint)); + status = A_EPROTO; + break; + } + } + + if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) { + /* somehow the lookahead that gave us the full read length did not + * reflect the actual header in the pending message */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags)); +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead"); + DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header"); +#ifdef HTC_CAPTURE_LAST_FRAME + DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header"); + if (target->LastTrailerLength != 0) { + DebugDumpBytes(target->LastTrailer, + target->LastTrailerLength, + "Last trailer"); + } +#endif +#endif + status = A_EPROTO; + break; + } + + /* get flags */ + temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags); + + if (temp & HTC_FLAGS_RECV_TRAILER) { + /* this packet has a trailer */ + + /* extract the trailer length in control byte 0 */ + temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]); + + if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", + payloadLen, temp)); + status = A_EPROTO; + break; + } + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + /* this packet was fetched as part of an HTC bundle, the embedded lookahead is + * not valid since the next packet may have already been fetched as part of the + * bundle */ + pNextLookAheads = NULL; + pNumLookAheads = NULL; + } + + /* process trailer data that follows HDR + application payload */ + status = HTCProcessTrailer(target, + (pBuf + HTC_HDR_LENGTH + payloadLen - temp), + temp, + pNextLookAheads, + pNumLookAheads, + pPacket->Endpoint); + + if (status) { + break; + } + +#ifdef HTC_CAPTURE_LAST_FRAME + memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp); + target->LastTrailerLength = temp; +#endif + /* trim length by trailer bytes */ + pPacket->ActualLength -= temp; + } +#ifdef HTC_CAPTURE_LAST_FRAME + else { + target->LastTrailerLength = 0; + } +#endif + + /* if we get to this point, the packet is good */ + /* remove header and adjust length */ + pPacket->pBuffer += HTC_HDR_LENGTH; + pPacket->ActualLength -= HTC_HDR_LENGTH; + + } while (false); + + if (status) { + /* dump the whole packet */ +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT"); +#endif + } else { +#ifdef HTC_CAPTURE_LAST_FRAME + memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr)); +#endif + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + if (pPacket->ActualLength > 0) { + AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg"); + } + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n")); + return status; +} + +static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target *target, + u32 NextLookAheads[], + int NumLookAheads, + bool CheckMoreMsgs) +{ + /* was there a lookahead for the next packet? */ + if (NumLookAheads > 0) { + int nextStatus; + int fetched = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n", + NumLookAheads)); + /* force status re-check */ + REF_IRQ_STATUS_RECHECK(&target->Device); + /* we have more packets, get the next packet fetch started */ + nextStatus = HTCRecvMessagePendingHandler(target, NextLookAheads, NumLookAheads, NULL, &fetched); + if (A_EPROTO == nextStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Next look ahead from recv header was INVALID\n")); +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes((u8 *)NextLookAheads, + NumLookAheads * (sizeof(u32)), + "BAD lookaheads from lookahead report"); +#endif + } + if (!nextStatus && !fetched) { + /* we could not fetch any more packets due to resources */ + DevAsyncIrqProcessComplete(&target->Device); + } + } else { + if (CheckMoreMsgs) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCAsyncRecvCheckMorePackets - rechecking for more messages...\n")); + /* if we did not get anything on the look-ahead, + * call device layer to asynchronously re-check for messages. If we can keep the async + * processing going we get better performance. If there is a pending message we will keep processing + * messages asynchronously which should pipeline things nicely */ + DevCheckPendingRecvMsgsAsync(&target->Device); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTCAsyncRecvCheckMorePackets - no check \n")); + } + } + + +} + + /* unload the recv completion queue */ +static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint) +{ + struct htc_packet_queue recvCompletions; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n")); + + INIT_HTC_PACKET_QUEUE(&recvCompletions); + + LOCK_HTC_RX(target); + + /* increment rx processing count on entry */ + pEndpoint->RxProcessCount++; + if (pEndpoint->RxProcessCount > 1) { + pEndpoint->RxProcessCount--; + /* another thread or task is draining the RX completion queue on this endpoint + * that thread will reset the rx processing count when the queue is drained */ + UNLOCK_HTC_RX(target); + return; + } + + /******* at this point only 1 thread may enter ******/ + + while (true) { + + /* transfer items from main recv queue to the local one so we can release the lock */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue); + + if (HTC_QUEUE_EMPTY(&recvCompletions)) { + /* all drained */ + break; + } + + /* release lock while we do the recv completions + * other threads can now queue more recv completions */ + UNLOCK_HTC_RX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DrainRecvIndicationQueue : completing %d RECV packets \n", + HTC_PACKET_QUEUE_DEPTH(&recvCompletions))); + /* do completion */ + DO_RCV_COMPLETION(pEndpoint,&recvCompletions); + + /* re-acquire lock to grab some more completions */ + LOCK_HTC_RX(target); + } + + /* reset count */ + pEndpoint->RxProcessCount = 0; + UNLOCK_HTC_RX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-DrainRecvIndicationQueue \n")); + +} + + /* optimization for recv packets, we can indicate a "hint" that there are more + * single-packets to fetch on this endpoint */ +#define SET_MORE_RX_PACKET_INDICATION_FLAG(L,N,E,P) \ + if ((N) > 0) { SetRxPacketIndicationFlags((L)[0],(E),(P)); } + + /* for bundled frames, we can force the flag to indicate there are more packets */ +#define FORCE_MORE_RX_PACKET_INDICATION_FLAG(P) \ + (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS; + + /* note: this function can be called with the RX lock held */ +static INLINE void SetRxPacketIndicationFlags(u32 LookAhead, + struct htc_endpoint *pEndpoint, + struct htc_packet *pPacket) +{ + struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead; + /* check to see if the "next" packet is from the same endpoint of the + completing packet */ + if (pHdr->EndpointID == pPacket->Endpoint) { + /* check that there is a buffer available to actually fetch it */ + if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) { + /* provide a hint that there are more RX packets to fetch */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + } +} + + +/* asynchronous completion handler for recv packet fetching, when the device layer + * completes a read request, it will call this completion handler */ +void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket) +{ + struct htc_target *target = (struct htc_target *)Context; + struct htc_endpoint *pEndpoint; + u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int numLookAheads = 0; + int status; + bool checkMorePkts = true; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n", + (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint)); + + A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device)); + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + pPacket->Completion = NULL; + + /* get completion status */ + status = pPacket->Status; + + do { + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n", + pPacket->Status, pPacket->Endpoint)); + break; + } + /* process the header for any trailer data */ + status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads); + + if (status) { + break; + } + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + /* this packet was part of a bundle that had to be broken up. + * It was fetched one message at a time. There may be other asynchronous reads queued behind this one. + * Do no issue another check for more packets since the last one in the series of requests + * will handle it */ + checkMorePkts = false; + } + + DUMP_RECV_PKT_INFO(pPacket); + LOCK_HTC_RX(target); + SET_MORE_RX_PACKET_INDICATION_FLAG(nextLookAheads,numLookAheads,pEndpoint,pPacket); + /* we have a good packet, queue it to the completion queue */ + HTC_PACKET_ENQUEUE(&pEndpoint->RecvIndicationQueue,pPacket); + HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads); + UNLOCK_HTC_RX(target); + + /* check for more recv packets before indicating */ + HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts); + + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n", + status)); + /* recycle this packet */ + HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint); + } else { + /* a good packet was queued, drain the queue */ + DrainRecvIndicationQueue(target,pEndpoint); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n")); +} + +/* synchronously wait for a control message from the target, + * This function is used at initialization time ONLY. At init messages + * on ENDPOINT 0 are expected. */ +int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket) +{ + int status; + u32 lookAhead; + struct htc_packet *pPacket = NULL; + struct htc_frame_hdr *pHdr; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n")); + + do { + + *ppControlPacket = NULL; + + /* call the polling function to see if we have a message */ + status = DevPollMboxMsgRecv(&target->Device, + &lookAhead, + HTC_TARGET_RESPONSE_TIMEOUT); + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead)); + + /* check the lookahead */ + pHdr = (struct htc_frame_hdr *)&lookAhead; + + if (pHdr->EndpointID != ENDPOINT_0) { + /* unexpected endpoint number, should be zero */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + if (status) { + /* bad message */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + pPacket = HTC_ALLOC_CONTROL_RX(target); + + if (pPacket == NULL) { + AR_DEBUG_ASSERT(false); + status = A_NO_MEMORY; + break; + } + + pPacket->PktInfo.AsRx.HTCRxFlags = 0; + pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead; + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; + + if (pPacket->ActualLength > pPacket->BufferLength) { + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + /* we want synchronous operation */ + pPacket->Completion = NULL; + + /* get the message from the device, this will block */ + status = HTCIssueRecv(target, pPacket); + + if (status) { + break; + } + + /* process receive header */ + status = HTCProcessRecvHeader(target,pPacket,NULL,NULL); + + pPacket->Status = status; + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n", + status)); + break; + } + + /* give the caller this control message packet, they are responsible to free */ + *ppControlPacket = pPacket; + + } while (false); + + if (status) { + if (pPacket != NULL) { + /* cleanup buffer on error */ + HTC_FREE_CONTROL_RX(target,pPacket); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n")); + + return status; +} + +static int AllocAndPrepareRxPackets(struct htc_target *target, + u32 LookAheads[], + int Messages, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue) +{ + int status = 0; + struct htc_packet *pPacket; + struct htc_frame_hdr *pHdr; + int i,j; + int numMessages; + int fullLength; + bool noRecycle; + + /* lock RX while we assemble the packet buffers */ + LOCK_HTC_RX(target); + + for (i = 0; i < Messages; i++) { + + pHdr = (struct htc_frame_hdr *)&LookAheads[i]; + + if (pHdr->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID)); + /* invalid endpoint */ + status = A_EPROTO; + break; + } + + if (pHdr->EndpointID != pEndpoint->Id) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d should be : %d (index:%d)\n", + pHdr->EndpointID, pEndpoint->Id, i)); + /* invalid endpoint */ + status = A_EPROTO; + break; + } + + if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n", + pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH)); + status = A_EPROTO; + break; + } + + if (0 == pEndpoint->ServiceID) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID)); + /* endpoint isn't even connected */ + status = A_EPROTO; + break; + } + + if ((pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) { + /* HTC header only indicates 1 message to fetch */ + numMessages = 1; + } else { + /* HTC header indicates that every packet to follow has the same padded length so that it can + * be optimally fetched as a full bundle */ + numMessages = (pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) >> HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT; + /* the count doesn't include the starter frame, just a count of frames to follow */ + numMessages++; + A_ASSERT(numMessages <= target->MaxMsgPerBundle); + INC_HTC_EP_STAT(pEndpoint, RxBundleIndFromHdr, 1); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages)); + } + + fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr)); + + /* get packet buffers for each message, if there was a bundle detected in the header, + * use pHdr as a template to fetch all packets in the bundle */ + for (j = 0; j < numMessages; j++) { + + /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup, + * they must be explicitly returned */ + noRecycle = false; + + if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) { + UNLOCK_HTC_RX(target); + noRecycle = true; + /* user is using a per-packet allocation callback */ + pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id, + fullLength); + LOCK_HTC_RX(target); + + } else if ((pEndpoint->EpCallBacks.EpRecvAllocThresh != NULL) && + (fullLength > pEndpoint->EpCallBacks.RecvAllocThreshold)) { + INC_HTC_EP_STAT(pEndpoint,RxAllocThreshHit,1); + INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen); + /* threshold was hit, call the special recv allocation callback */ + UNLOCK_HTC_RX(target); + noRecycle = true; + /* user wants to allocate packets above a certain threshold */ + pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id, + fullLength); + LOCK_HTC_RX(target); + + } else { + /* user is using a refill handler that can refill multiple HTC buffers */ + + /* get a packet from the endpoint recv queue */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); + + if (NULL == pPacket) { + /* check for refill handler */ + if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) { + UNLOCK_HTC_RX(target); + /* call the re-fill handler */ + pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id); + LOCK_HTC_RX(target); + /* check if we have more buffers */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); + /* fall through */ + } + } + } + + if (NULL == pPacket) { + /* this is not an error, we simply need to mark that we are waiting for buffers.*/ + target->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = pEndpoint->Id; + status = A_NO_RESOURCE; + break; + } + + AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id); + /* clear flags */ + pPacket->PktInfo.AsRx.HTCRxFlags = 0; + pPacket->PktInfo.AsRx.IndicationFlags = 0; + pPacket->Status = 0; + + if (noRecycle) { + /* flag that these packets cannot be recycled, they have to be returned to the + * user */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE; + } + /* add packet to queue (also incase we need to cleanup down below) */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + + if (HTC_STOPPING(target)) { + status = A_ECANCELED; + break; + } + + /* make sure this message can fit in the endpoint buffer */ + if ((u32)fullLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n", + pHdr->PayloadLen, fullLength, pPacket->BufferLength)); + status = A_EPROTO; + break; + } + + if (j > 0) { + /* for messages fetched in a bundle the expected lookahead is unknown since we + * are only using the lookahead of the first packet as a template of what to + * expect for lengths */ + /* flag that once we get the real HTC header we need to refesh the information */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR; + /* set it to something invalid */ + pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF; + } else { + + pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */ + } + /* set the amount of data to fetch */ + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; + } + + if (status) { + if (A_NO_RESOURCE == status) { + /* this is actually okay */ + status = 0; + } + break; + } + + } + + UNLOCK_HTC_RX(target); + + if (status) { + while (!HTC_QUEUE_EMPTY(pQueue)) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* recycle all allocated packets */ + HTC_RECYCLE_RX_PKT(target,pPacket,&target->EndPoint[pPacket->Endpoint]); + } + } + + return status; +} + +static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq) +{ + int i; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint; + u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int numLookAheads = 0; + struct htc_target *target = (struct htc_target *)pScatterReq->Context; + int status; + bool partialBundle = false; + struct htc_packet_queue localRecvQueue; + bool procError = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion TotLen: %d Entries: %d\n", + pScatterReq->TotalLength, pScatterReq->ValidScatterEntries)); + + A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device)); + + if (pScatterReq->CompletionStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus)); + } + + if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) { + partialBundle = true; + } + + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + + INIT_HTC_PACKET_QUEUE(&localRecvQueue); + + pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0]; + /* note: all packets in a scatter req are for the same endpoint ! */ + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + /* walk through the scatter list and process */ + /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock + * as it processes credit reports */ + for (i = 0; i < pScatterReq->ValidScatterEntries; i++) { + pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0]; + A_ASSERT(pPacket != NULL); + /* reset count, we are only interested in the look ahead in the last packet when we + * break out of this loop */ + numLookAheads = 0; + + if (!pScatterReq->CompletionStatus) { + /* process header for each of the recv packets */ + status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads); + } else { + status = A_ERROR; + } + + if (!status) { + LOCK_HTC_RX(target); + HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads); + INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1); + UNLOCK_HTC_RX(target); + if (i == (pScatterReq->ValidScatterEntries - 1)) { + /* last packet's more packets flag is set based on the lookahead */ + SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,numLookAheads,pEndpoint,pPacket); + } else { + /* packets in a bundle automatically have this flag set */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + + DUMP_RECV_PKT_INFO(pPacket); + /* since we can't hold a lock in this loop, we insert into our local recv queue for + * storage until we can transfer them to the recv completion queue */ + HTC_PACKET_ENQUEUE(&localRecvQueue,pPacket); + + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Recv packet scatter entry %d failed (out of %d) \n", + i, pScatterReq->ValidScatterEntries)); + /* recycle failed recv */ + HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint); + /* set flag and continue processing the remaining scatter entries */ + procError = true; + } + + } + + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + + LOCK_HTC_RX(target); + /* transfer the packets in the local recv queue to the recv completion queue */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RecvIndicationQueue, &localRecvQueue); + + UNLOCK_HTC_RX(target); + + if (!procError) { + /* pipeline the next check (asynchronously) for more packets */ + HTCAsyncRecvCheckMorePackets(target, + lookAheads, + numLookAheads, + partialBundle ? false : true); + } + + /* now drain the indication queue */ + DrainRecvIndicationQueue(target,pEndpoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n")); +} + +static int HTCIssueRecvPacketBundle(struct htc_target *target, + struct htc_packet_queue *pRecvPktQueue, + struct htc_packet_queue *pSyncCompletionQueue, + int *pNumPacketsFetched, + bool PartialBundle) +{ + int status = 0; + struct hif_scatter_req *pScatterReq; + int i, totalLength; + int pktsToScatter; + struct htc_packet *pPacket; + bool asyncMode = (pSyncCompletionQueue == NULL) ? true : false; + int scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device); + + pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue); + pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle); + + if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) { + /* we were forced to split this bundle receive operation + * all packets in this partial bundle must have their lookaheads ignored */ + PartialBundle = true; + /* this would only happen if the target ignored our max bundle limit */ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n", + HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter)); + } + + totalLength = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCIssueRecvPacketBundle (Numpackets: %d , actual : %d) \n", + HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter)); + + do { + + pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device); + + if (pScatterReq == NULL) { + /* no scatter resources left, just let caller handle it the legacy way */ + break; + } + + pScatterReq->CallerFlags = 0; + + if (PartialBundle) { + /* mark that this is a partial bundle, this has special ramifications to the + * scatter completion routine */ + pScatterReq->CallerFlags |= HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE; + } + + /* convert HTC packets to scatter list */ + for (i = 0; i < pktsToScatter; i++) { + int paddedLength; + + pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue); + A_ASSERT(pPacket != NULL); + + paddedLength = DEV_CALC_RECV_PADDED_LEN(&target->Device, pPacket->ActualLength); + + if ((scatterSpaceRemaining - paddedLength) < 0) { + /* exceeds what we can transfer, put the packet back */ + HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue,pPacket); + break; + } + + scatterSpaceRemaining -= paddedLength; + + if (PartialBundle || (i < (pktsToScatter - 1))) { + /* packet 0..n-1 cannot be checked for look-aheads since we are fetching a bundle + * the last packet however can have it's lookahead used */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } + + /* note: 1 HTC packet per scatter entry */ + /* setup packet into */ + pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer; + pScatterReq->ScatterList[i].Length = paddedLength; + + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE; + + if (asyncMode) { + /* save HTC packet for async completion routine */ + pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket; + } else { + /* queue to caller's sync completion queue, caller will unload this when we return */ + HTC_PACKET_ENQUEUE(pSyncCompletionQueue,pPacket); + } + + A_ASSERT(pScatterReq->ScatterList[i].Length); + totalLength += pScatterReq->ScatterList[i].Length; + } + + pScatterReq->TotalLength = totalLength; + pScatterReq->ValidScatterEntries = i; + + if (asyncMode) { + pScatterReq->CompletionRoutine = HTCAsyncRecvScatterCompletion; + pScatterReq->Context = target; + } + + status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode); + + if (!status) { + *pNumPacketsFetched = i; + } + + if (!asyncMode) { + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n", + status,*pNumPacketsFetched)); + + return status; +} + +static INLINE void CheckRecvWaterMark(struct htc_endpoint *pEndpoint) +{ + /* see if endpoint is using a refill watermark + * ** no need to use a lock here, since we are only inspecting... + * caller may must not hold locks when calling this function */ + if (pEndpoint->EpCallBacks.RecvRefillWaterMark > 0) { + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBuffers) < pEndpoint->EpCallBacks.RecvRefillWaterMark) { + /* call the re-fill handler before we continue */ + pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id); + } + } +} + +/* callback when device layer or lookahead report parsing detects a pending message */ +int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched) +{ + struct htc_target *target = (struct htc_target *)Context; + int status = 0; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint; + bool asyncProc = false; + u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int pktsFetched; + struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue; + bool partialBundle; + HTC_ENDPOINT_ID id; + int totalFetched = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler NumLookAheads: %d \n",NumLookAheads)); + + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = 0; + } + + if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) { + /* We use async mode to get the packets if the device layer supports it. + * The device layer interfaces with HIF in which HIF may have restrictions on + * how interrupts are processed */ + asyncProc = true; + } + + if (pAsyncProc != NULL) { + /* indicate to caller how we decided to process this */ + *pAsyncProc = asyncProc; + } + + if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) { + A_ASSERT(false); + return A_EPROTO; + } + + /* on first entry copy the lookaheads into our temp array for processing */ + memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads); + + while (true) { + + /* reset packets queues */ + INIT_HTC_PACKET_QUEUE(&recvPktQueue); + INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue); + + if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) { + status = A_EPROTO; + A_ASSERT(false); + break; + } + + /* first lookahead sets the expected endpoint IDs for all packets in a bundle */ + id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID; + pEndpoint = &target->EndPoint[id]; + + if (id >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MsgPend, Invalid Endpoint in look-ahead: %d \n",id)); + status = A_EPROTO; + break; + } + + /* try to allocate as many HTC RX packets indicated by the lookaheads + * these packets are stored in the recvPkt queue */ + status = AllocAndPrepareRxPackets(target, + lookAheads, + NumLookAheads, + pEndpoint, + &recvPktQueue); + if (status) { + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) >= 2) { + /* a recv bundle was detected, force IRQ status re-check again */ + REF_IRQ_STATUS_RECHECK(&target->Device); + } + + totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue); + + /* we've got packet buffers for all we can currently fetch, + * this count is not valid anymore */ + NumLookAheads = 0; + partialBundle = false; + + /* now go fetch the list of HTC packets */ + while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { + + pktsFetched = 0; + + if (target->RecvBundlingEnabled && (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) { + /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */ + status = HTCIssueRecvPacketBundle(target, + &recvPktQueue, + asyncProc ? NULL : &syncCompletedPktsQueue, + &pktsFetched, + partialBundle); + if (status) { + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) { + /* we couldn't fetch all packets at one time, this creates a broken + * bundle */ + partialBundle = true; + } + } + + /* see if the previous operation fetched any packets using bundling */ + if (0 == pktsFetched) { + /* dequeue one packet */ + pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue); + A_ASSERT(pPacket != NULL); + + if (asyncProc) { + /* we use async mode to get the packet if the device layer supports it + * set our callback and context */ + pPacket->Completion = HTCRecvCompleteHandler; + pPacket->pContext = target; + } else { + /* fully synchronous */ + pPacket->Completion = NULL; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) { + /* lookaheads in all packets except the last one in the bundle must be ignored */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } + + /* go fetch the packet */ + status = HTCIssueRecv(target, pPacket); + if (status) { + break; + } + + if (!asyncProc) { + /* sent synchronously, queue this packet for synchronous completion */ + HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue,pPacket); + } + + } + + } + + if (!status) { + CheckRecvWaterMark(pEndpoint); + } + + if (asyncProc) { + /* we did this asynchronously so we can get out of the loop, the asynch processing + * creates a chain of requests to continue processing pending messages in the + * context of callbacks */ + break; + } + + /* synchronous handling */ + if (target->Device.DSRCanYield) { + /* for the SYNC case, increment count that tracks when the DSR should yield */ + target->Device.CurrentDSRRecvCount++; + } + + /* in the sync case, all packet buffers are now filled, + * we can process each packet, check lookaheads and then repeat */ + + /* unload sync completion queue */ + while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + struct htc_packet_queue container; + + pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue); + A_ASSERT(pPacket != NULL); + + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + /* reset count on each iteration, we are only interested in the last packet's lookahead + * information when we break out of this loop */ + NumLookAheads = 0; + /* process header for each of the recv packets + * note: the lookahead of the last packet is useful for us to continue in this loop */ + status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads); + if (status) { + break; + } + + if (HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + /* last packet's more packets flag is set based on the lookahead */ + SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,NumLookAheads,pEndpoint,pPacket); + } else { + /* packets in a bundle automatically have this flag set */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + /* good packet, indicate it */ + HTC_RX_STAT_PROFILE(target,pEndpoint,NumLookAheads); + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_PART_OF_BUNDLE) { + INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1); + } + + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + DO_RCV_COMPLETION(pEndpoint,&container); + } + + if (status) { + break; + } + + if (NumLookAheads == 0) { + /* no more look aheads */ + break; + } + + /* when we process recv synchronously we need to check if we should yield and stop + * fetching more packets indicated by the embedded lookaheads */ + if (target->Device.DSRCanYield) { + if (DEV_CHECK_RECV_YIELD(&target->Device)) { + /* break out, don't fetch any more packets */ + break; + } + } + + + /* check whether other OS contexts have queued any WMI command/data for WLAN. + * This check is needed only if WLAN Tx and Rx happens in same thread context */ + A_CHECK_DRV_TX(); + + /* for SYNCH processing, if we get here, we are running through the loop again due to a detected lookahead. + * Set flag that we should re-check IRQ status registers again before leaving IRQ processing, + * this can net better performance in high throughput situations */ + REF_IRQ_STATUS_RECHECK(&target->Device); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to get pending recv messages (%d) \n",status)); + /* cleanup any packets we allocated but didn't use to actually fetch any packets */ + while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue); + /* clean up packets */ + HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]); + } + /* cleanup any packets in sync completion queue */ + while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue); + /* clean up packets */ + HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]); + } + if (HTC_STOPPING(target)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + (" Host is going to stop. blocking receiver for HTCStop.. \n")); + DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC); + } + } + /* before leaving, check to see if host ran out of buffers and needs to stop the + * receiver */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + (" Host has no RX buffers, blocking receiver to prevent overrun.. \n")); + /* try to stop receive at the device layer */ + DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC); + } + + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = totalFetched; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n")); + + return status; +} + +int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint; + bool unblockRecv = false; + int status = 0; + struct htc_packet *pFirstPacket; + + pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + + if (NULL == pFirstPacket) { + A_ASSERT(false); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n", + pFirstPacket->Endpoint, + HTC_PACKET_QUEUE_DEPTH(pPktQueue), + pFirstPacket->BufferLength)); + + do { + + pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; + + LOCK_HTC_RX(target); + + if (HTC_STOPPING(target)) { + struct htc_packet *pPacket; + + UNLOCK_HTC_RX(target); + + /* walk through queue and mark each one canceled */ + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + pPacket->Status = A_ECANCELED; + } HTC_PACKET_QUEUE_ITERATE_END; + + DO_RCV_COMPLETION(pEndpoint,pPktQueue); + break; + } + + /* store receive packets */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBuffers, pPktQueue); + + /* check if we are blocked waiting for a new buffer */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + if (target->EpWaitingForBuffers == pFirstPacket->Endpoint) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n", + target->EpWaitingForBuffers)); + target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = ENDPOINT_MAX; + unblockRecv = true; + } + } + + UNLOCK_HTC_RX(target); + + if (unblockRecv && !HTC_STOPPING(target)) { + /* TODO : implement a buffer threshold count? */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } + + } while (false); + + return status; +} + +/* Makes a buffer available to the HTC module */ +int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket) +{ + struct htc_packet_queue queue; + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCAddReceivePktMultiple(HTCHandle, &queue); +} + +void HTCUnblockRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + bool unblockRecv = false; + + LOCK_HTC_RX(target); + + /* check if we are blocked waiting for a new buffer */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n", + target->EpWaitingForBuffers)); + target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = ENDPOINT_MAX; + unblockRecv = true; + } + + UNLOCK_HTC_RX(target); + + if (unblockRecv && !HTC_STOPPING(target)) { + /* re-enable */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC); + } +} + +static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue) +{ + struct htc_packet *pPacket; + struct htc_packet_queue container; + + LOCK_HTC_RX(target); + + while (1) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + if (NULL == pPacket) { + break; + } + UNLOCK_HTC_RX(target); + pPacket->Status = A_ECANCELED; + pPacket->ActualLength = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%lX, length:%d, ep:%d \n", + (unsigned long)pPacket, pPacket->BufferLength, pPacket->Endpoint)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* give the packet back */ + DO_RCV_COMPLETION(pEndpoint,&container); + LOCK_HTC_RX(target); + } + + UNLOCK_HTC_RX(target); +} + +static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint) +{ + /* flush any recv indications not already made */ + HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue); + /* flush any rx buffers */ + HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers); +} + +void HTCFlushRecvBuffers(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID == 0) { + /* not in use.. */ + continue; + } + HTCFlushEndpointRX(target,pEndpoint); + } +} + + +void HTCEnableRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + if (!HTC_STOPPING(target)) { + /* re-enable */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } +} + +void HTCDisableRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + if (!HTC_STOPPING(target)) { + /* disable */ + DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } +} + +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers)); +} + +int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle, + u32 TimeoutInMs, + bool *pbIsRecvPending) +{ + int status = 0; + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + status = DevWaitForPendingRecv(&target->Device, + TimeoutInMs, + pbIsRecvPending); + + return status; +} diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_send.c b/trunk/drivers/staging/ath6kl/htc2/htc_send.c new file mode 100644 index 000000000000..9310d4d5c992 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_send.c @@ -0,0 +1,1018 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +typedef enum _HTC_SEND_QUEUE_RESULT { + HTC_SEND_QUEUE_OK = 0, /* packet was queued */ + HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */ +} HTC_SEND_QUEUE_RESULT; + +#define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q) + +/* call the distribute credits callback with the distribution */ +#define DO_DISTRIBUTION(t,reason,description,pList) \ +{ \ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \ + (" calling distribute function (%s) (dfn:0x%lX, ctxt:0x%lX, dist:0x%lX) \n", \ + (description), \ + (unsigned long)(t)->DistributeCredits, \ + (unsigned long)(t)->pCredDistContext, \ + (unsigned long)pList)); \ + (t)->DistributeCredits((t)->pCredDistContext, \ + (pList), \ + (reason)); \ +} + +static void DoSendCompletion(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueueToIndicate) +{ + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a multiple send complete handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + /* all packets are now owned by the callback, reset queue to be safe */ + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + struct htc_packet *pPacket; + /* using legacy EpTxComplete */ + do { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet 0x%lX \n", \ + pEndpoint->Id, (unsigned long)(pPacket))); + pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket); + } while (!HTC_QUEUE_EMPTY(pQueueToIndicate)); + } + + } while (false); + +} + +/* do final completion on sent packet */ +static INLINE void CompleteSentPacket(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet *pPacket) +{ + pPacket->Completion = NULL; + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n", + pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed)); + /* on failure to submit, reclaim credits for this packet */ + LOCK_HTC_TX(target); + pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUsed; + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEND_COMPLETE, + "Send Complete", + target->EpCreditDistributionListHead->pNext); + UNLOCK_HTC_TX(target); + } + /* first, fixup the head room we allocated */ + pPacket->pBuffer += HTC_HDR_LENGTH; +} + +/* our internal send packet completion handler when packets are submited to the AR6K device + * layer */ +static void HTCSendPktCompletionHandler(void *Context, struct htc_packet *pPacket) +{ + struct htc_target *target = (struct htc_target *)Context; + struct htc_endpoint *pEndpoint = &target->EndPoint[pPacket->Endpoint]; + struct htc_packet_queue container; + + CompleteSentPacket(target,pEndpoint,pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* do completion */ + DO_EP_TX_COMPLETION(pEndpoint,&container); +} + +int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket) +{ + int status; + bool sync = false; + + if (pPacket->Completion == NULL) { + /* mark that this request was synchronously issued */ + sync = true; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-HTCIssueSend: transmit length : %d (%s) \n", + pPacket->ActualLength + (u32)HTC_HDR_LENGTH, + sync ? "SYNC" : "ASYNC" )); + + /* send message to device */ + status = DevSendPacket(&target->Device, + pPacket, + pPacket->ActualLength + HTC_HDR_LENGTH); + + if (sync) { + /* use local sync variable. If this was issued asynchronously, pPacket is no longer + * safe to access. */ + pPacket->pBuffer += HTC_HDR_LENGTH; + } + + /* if this request was asynchronous, the packet completion routine will be invoked by + * the device layer when the HIF layer completes the request */ + + return status; +} + + /* get HTC send packets from the TX queue on an endpoint */ +static INLINE void GetHTCSendPackets(struct htc_target *target, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue) +{ + int creditsRequired; + int remainder; + u8 sendFlags; + struct htc_packet *pPacket; + unsigned int transferLength; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n")); + + /* loop until we can grab as many packets out of the queue as we can */ + while (true) { + + sendFlags = 0; + /* get packet at head, but don't remove it */ + pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue); + if (pPacket == NULL) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%lX , Queue Depth: %d\n", + (unsigned long)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + + transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->ActualLength + HTC_HDR_LENGTH); + + if (transferLength <= target->TargetCreditSize) { + creditsRequired = 1; + } else { + /* figure out how many credits this message requires */ + creditsRequired = transferLength / target->TargetCreditSize; + remainder = transferLength % target->TargetCreditSize; + + if (remainder) { + creditsRequired++; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n", + creditsRequired, pEndpoint->CreditDist.TxCredits)); + + if (pEndpoint->CreditDist.TxCredits < creditsRequired) { + + /* not enough credits */ + if (pPacket->Endpoint == ENDPOINT_0) { + /* leave it in the queue */ + break; + } + /* invoke the registered distribution function only if this is not + * endpoint 0, we let the driver layer provide more credits if it can. + * We pass the credit distribution list starting at the endpoint in question + * */ + + /* set how many credits we need */ + pEndpoint->CreditDist.TxCreditsSeek = + creditsRequired - pEndpoint->CreditDist.TxCredits; + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEEK_CREDITS, + "Seek Credits", + &pEndpoint->CreditDist); + pEndpoint->CreditDist.TxCreditsSeek = 0; + + if (pEndpoint->CreditDist.TxCredits < creditsRequired) { + /* still not enough credits to send, leave packet in the queue */ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Not enough credits for ep %d leaving packet in queue..\n", + pPacket->Endpoint)); + break; + } + + } + + pEndpoint->CreditDist.TxCredits -= creditsRequired; + INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired); + + /* check if we need credits back from the target */ + if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + /* we are getting low on credits, see if we can ask for more from the distribution function */ + pEndpoint->CreditDist.TxCreditsSeek = + pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits; + + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEEK_CREDITS, + "Seek Credits", + &pEndpoint->CreditDist); + + pEndpoint->CreditDist.TxCreditsSeek = 0; + /* see if we were successful in getting more */ + if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + /* tell the target we need credits ASAP! */ + sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; + INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n")); + } + } + + /* now we can fully dequeue */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue); + /* save the number of credits this packet consumed */ + pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired; + /* all TX packets are handled asynchronously */ + pPacket->Completion = HTCSendPktCompletionHandler; + pPacket->pContext = target; + INC_HTC_EP_STAT(pEndpoint, TxIssued, 1); + /* save send flags */ + pPacket->PktInfo.AsTx.SendFlags = sendFlags; + pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; + pEndpoint->SeqNo++; + /* queue this packet into the caller's queue */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n")); + +} + +static void HTCAsyncSendScatterCompletion(struct hif_scatter_req *pScatterReq) +{ + int i; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint = (struct htc_endpoint *)pScatterReq->Context; + struct htc_target *target = (struct htc_target *)pEndpoint->target; + int status = 0; + struct htc_packet_queue sendCompletes; + + INIT_HTC_PACKET_QUEUE(&sendCompletes); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n", + pScatterReq->TotalLength, pScatterReq->ValidScatterEntries)); + + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + + if (pScatterReq->CompletionStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus)); + status = A_ERROR; + } + + /* walk through the scatter list and process */ + for (i = 0; i < pScatterReq->ValidScatterEntries; i++) { + pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]); + A_ASSERT(pPacket != NULL); + pPacket->Status = status; + CompleteSentPacket(target,pEndpoint,pPacket); + /* add it to the completion queue */ + HTC_PACKET_ENQUEUE(&sendCompletes, pPacket); + } + + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + /* complete all packets */ + DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n")); +} + + /* drain a queue and send as bundles + * this function may return without fully draining the queue under the following conditions : + * - scatter resources are exhausted + * - a message that will consume a partial credit will stop the bundling process early + * - we drop below the minimum number of messages for a bundle + * */ +static void HTCIssueSendBundle(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue, + int *pBundlesSent, + int *pTotalBundlesPkts) +{ + int pktsToScatter; + unsigned int scatterSpaceRemaining; + struct hif_scatter_req *pScatterReq = NULL; + int i, packetsInScatterReq; + unsigned int transferLength; + struct htc_packet *pPacket; + bool done = false; + int bundlesSent = 0; + int totalPktsInBundle = 0; + struct htc_target *target = pEndpoint->target; + int creditRemainder = 0; + int creditPad; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n")); + + while (!done) { + + pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue); + pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle); + + if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) { + /* not enough to bundle */ + break; + } + + pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device); + + if (pScatterReq == NULL) { + /* no scatter resources */ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatter)); + + pScatterReq->TotalLength = 0; + pScatterReq->ValidScatterEntries = 0; + + packetsInScatterReq = 0; + scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device); + + for (i = 0; i < pktsToScatter; i++) { + + pScatterReq->ScatterList[i].pCallerContexts[0] = NULL; + + pPacket = HTC_GET_PKT_AT_HEAD(pQueue); + if (pPacket == NULL) { + A_ASSERT(false); + break; + } + + creditPad = 0; + transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, + pPacket->ActualLength + HTC_HDR_LENGTH); + /* see if the padded transfer length falls on a credit boundary */ + creditRemainder = transferLength % target->TargetCreditSize; + + if (creditRemainder != 0) { + /* the transfer consumes a "partial" credit, this packet cannot be bundled unless + * we add additional "dummy" padding (max 255 bytes) to consume the entire credit + *** NOTE: only allow the send padding if the endpoint is allowed to */ + if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING) { + if (transferLength < target->TargetCreditSize) { + /* special case where the transfer is less than a credit */ + creditPad = target->TargetCreditSize - transferLength; + } else { + creditPad = creditRemainder; + } + + /* now check to see if we can indicate padding in the HTC header */ + if ((creditPad > 0) && (creditPad <= 255)) { + /* adjust the transferlength of this packet with the new credit padding */ + transferLength += creditPad; + } else { + /* the amount to pad is too large, bail on this packet, we have to + * send it using the non-bundled method */ + pPacket = NULL; + } + } else { + /* bail on this packet, user does not want padding applied */ + pPacket = NULL; + } + } + + if (NULL == pPacket) { + /* can't bundle */ + done = true; + break; + } + + if (scatterSpaceRemaining < transferLength) { + /* exceeds what we can transfer */ + break; + } + + scatterSpaceRemaining -= transferLength; + /* now remove it from the queue */ + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* save it in the scatter list */ + pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket; + /* prepare packet and flag message as part of a send bundle */ + HTC_PREPARE_SEND_PKT(pPacket, + pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE, + creditPad, + pPacket->PktInfo.AsTx.SeqNo); + pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer; + pScatterReq->ScatterList[i].Length = transferLength; + A_ASSERT(transferLength); + pScatterReq->TotalLength += transferLength; + pScatterReq->ValidScatterEntries++; + packetsInScatterReq++; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%lX, len:%d (remaining space:%d) \n", + i, (unsigned long)pPacket,transferLength,scatterSpaceRemaining)); + } + + if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) { + /* send path is always asynchronous */ + pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion; + pScatterReq->Context = pEndpoint; + bundlesSent++; + totalPktsInBundle += packetsInScatterReq; + packetsInScatterReq = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , entries: %d\n", + pScatterReq->TotalLength,pScatterReq->ValidScatterEntries)); + DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WRITE, DEV_SCATTER_ASYNC); + /* we don't own this anymore */ + pScatterReq = NULL; + /* try to send some more */ + continue; + } + + /* not enough packets to use the scatter request, cleanup */ + if (pScatterReq != NULL) { + if (packetsInScatterReq > 0) { + /* work backwards to requeue requests */ + for (i = (packetsInScatterReq - 1); i >= 0; i--) { + pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]); + if (pPacket != NULL) { + /* undo any prep */ + HTC_UNPREPARE_SEND_PKT(pPacket); + /* queue back to the head */ + HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket); + } + } + } + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + } + + /* if we get here, we sent all that we could, get out */ + break; + + } + + *pBundlesSent = bundlesSent; + *pTotalBundlesPkts = totalPktsInBundle; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSent)); + + return; +} + +/* + * if there are no credits, the packet(s) remains in the queue. + * this function returns the result of the attempt to send a queue of HTC packets */ +static HTC_SEND_QUEUE_RESULT HTCTrySend(struct htc_target *target, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pCallersSendQueue) +{ + struct htc_packet_queue sendQueue; /* temp queue to hold packets at various stages */ + struct htc_packet *pPacket; + int bundlesSent; + int pktsInBundles; + int overflow; + HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%lX Depth:%d)\n", + (unsigned long)pCallersSendQueue, + (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue))); + + /* init the local send queue */ + INIT_HTC_PACKET_QUEUE(&sendQueue); + + do { + + if (NULL == pCallersSendQueue) { + /* caller didn't provide a queue, just wants us to check queues and send */ + break; + } + + if (HTC_QUEUE_EMPTY(pCallersSendQueue)) { + /* empty queue */ + result = HTC_SEND_QUEUE_DROP; + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) { + /* we've already overflowed */ + overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + } else { + /* figure out how much we will overflow by */ + overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + /* figure out how much we will overflow the TX queue by */ + overflow -= pEndpoint->MaxTxQueueDepth; + } + + /* if overflow is negative or zero, we are okay */ + if (overflow > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n", + pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth)); + } + if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) { + /* all packets will fit or caller did not provide send full indication handler + * -- just move all of them to the local sendQueue object */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue); + } else { + int i; + int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow; + + A_ASSERT(goodPkts >= 0); + /* we have overflowed, and a callback is provided */ + /* dequeue all non-overflow packets into the sendqueue */ + for (i = 0; i < goodPkts; i++) { + /* pop off caller's queue*/ + pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue); + A_ASSERT(pPacket != NULL); + /* insert into local queue */ + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + /* the caller's queue has all the packets that won't fit*/ + /* walk through the caller's queue and indicate each one to the send full handler */ + ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, struct htc_packet, ListLink) { + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n", + (unsigned long)pPacket)); + if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, + pPacket) == HTC_SEND_FULL_DROP) { + /* callback wants the packet dropped */ + INC_HTC_EP_STAT(pEndpoint, TxDropped, 1); + /* leave this one in the caller's queue for cleanup */ + } else { + /* callback wants to keep this packet, remove from caller's queue */ + HTC_PACKET_REMOVE(pCallersSendQueue, pPacket); + /* put it in the send queue */ + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + } ITERATE_END; + + if (HTC_QUEUE_EMPTY(&sendQueue)) { + /* no packets made it in, caller will cleanup */ + result = HTC_SEND_QUEUE_DROP; + break; + } + } + + } while (false); + + if (result != HTC_SEND_QUEUE_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + return result; + } + + LOCK_HTC_TX(target); + + if (!HTC_QUEUE_EMPTY(&sendQueue)) { + /* transfer packets */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue); + A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue)); + INIT_HTC_PACKET_QUEUE(&sendQueue); + } + + /* increment tx processing count on entry */ + pEndpoint->TxProcessCount++; + if (pEndpoint->TxProcessCount > 1) { + /* another thread or task is draining the TX queues on this endpoint + * that thread will reset the tx processing count when the queue is drained */ + pEndpoint->TxProcessCount--; + UNLOCK_HTC_TX(target); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n")); + return HTC_SEND_QUEUE_OK; + } + + /***** beyond this point only 1 thread may enter ******/ + + /* now drain the endpoint TX queue for transmission as long as we have enough + * credits */ + while (true) { + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) { + break; + } + + /* get all the packets for this endpoint that we can for this pass */ + GetHTCSendPackets(target, pEndpoint, &sendQueue); + + if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) { + /* didn't get any packets due to a lack of credits */ + break; + } + + UNLOCK_HTC_TX(target); + + /* any packets to send are now in our local send queue */ + + bundlesSent = 0; + pktsInBundles = 0; + + while (true) { + + /* try to send a bundle on each pass */ + if ((target->SendBundlingEnabled) && + (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_BUNDLE)) { + int temp1,temp2; + /* bundling is enabled and there is at least a minimum number of packets in the send queue + * send what we can in this pass */ + HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2); + bundlesSent += temp1; + pktsInBundles += temp2; + } + + /* if not bundling or there was a packet that could not be placed in a bundle, pull it out + * and send it the normal way */ + pPacket = HTC_PACKET_DEQUEUE(&sendQueue); + if (NULL == pPacket) { + /* local queue is fully drained */ + break; + } + HTC_PREPARE_SEND_PKT(pPacket, + pPacket->PktInfo.AsTx.SendFlags, + 0, + pPacket->PktInfo.AsTx.SeqNo); + HTCIssueSend(target, pPacket); + + /* go back and see if we can bundle some more */ + } + + LOCK_HTC_TX(target); + + INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent); + INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles); + + } + + /* done with this endpoint, we can clear the count */ + pEndpoint->TxProcessCount = 0; + UNLOCK_HTC_TX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + + return HTC_SEND_QUEUE_OK; +} + +int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint; + struct htc_packet *pPacket; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n", + (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); + + /* get packet at head to figure out which endpoint these packets will go into */ + pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + if (NULL == pPacket) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + HTCTrySend(target, pEndpoint, pPktQueue); + + /* do completion on any packets that couldn't get in */ + if (!HTC_QUEUE_EMPTY(pPktQueue)) { + + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + if (HTC_STOPPING(target)) { + pPacket->Status = A_ECANCELED; + } else { + pPacket->Status = A_NO_RESOURCE; + } + } HTC_PACKET_QUEUE_ITERATE_END; + + DO_EP_TX_COMPLETION(pEndpoint,pPktQueue); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + + return 0; +} + +/* HTC API - HTCSendPkt */ +int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket) +{ + struct htc_packet_queue queue; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n", + pPacket->Endpoint, (unsigned long)pPacket->pBuffer, pPacket->ActualLength)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCSendPktsMultiple(HTCHandle, &queue); +} + +/* check TX queues to drain because of credit distribution update */ +static INLINE void HTCCheckEndpointTxQueues(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + struct htc_endpoint_credit_dist *pDistItem; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n")); + pDistItem = target->EpCreditDistributionListHead; + + /* run through the credit distribution list to see + * if there are packets queued + * NOTE: no locks need to be taken since the distribution list + * is not dynamic (cannot be re-ordered) and we are not modifying any state */ + while (pDistItem != NULL) { + pEndpoint = (struct htc_endpoint *)pDistItem->pHTCReserved; + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n", + pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + /* try to start the stalled queue, this list is ordered by priority. + * Highest priority queue get's processed first, if there are credits available the + * highest priority queue will get a chance to reclaim credits from lower priority + * ones */ + HTCTrySend(target, pEndpoint, NULL); + } + + pDistItem = pDistItem->pNext; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n")); +} + +/* process credit reports and call distribution function */ +void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint) +{ + int i; + struct htc_endpoint *pEndpoint; + int totalCredits = 0; + bool doDist = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries)); + + /* lock out TX while we update credits */ + LOCK_HTC_TX(target); + + for (i = 0; i < NumEntries; i++, pRpt++) { + if (pRpt->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(false); + break; + } + + pEndpoint = &target->EndPoint[pRpt->EndpointID]; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n", + pRpt->EndpointID, pRpt->Credits)); + + INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1); + INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits); + + if (FromEndpoint == pRpt->EndpointID) { + /* this credit report arrived on the same endpoint indicating it arrived in an RX + * packet */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1); + } else if (FromEndpoint == ENDPOINT_0) { + /* this credit arrived on endpoint 0 as a NULL message */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1); + } else { + /* arrived on another endpoint */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1); + } + + if (ENDPOINT_0 == pRpt->EndpointID) { + /* always give endpoint 0 credits back */ + pEndpoint->CreditDist.TxCredits += pRpt->Credits; + } else { + /* for all other endpoints, update credits to distribute, the distribution function + * will handle giving out credits back to the endpoints */ + pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits; + /* flag that we have to do the distribution */ + doDist = true; + } + + /* refresh tx depth for distribution function that will recover these credits + * NOTE: this is only valid when there are credits to recover! */ + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + + totalCredits += pRpt->Credits; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits)); + + if (doDist) { + /* this was a credit return based on a completed send operations + * note, this is done with the lock held */ + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEND_COMPLETE, + "Send Complete", + target->EpCreditDistributionListHead->pNext); + } + + UNLOCK_HTC_TX(target); + + if (totalCredits) { + HTCCheckEndpointTxQueues(target); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n")); +} + +/* flush endpoint TX queue */ +static void HTCFlushEndpointTX(struct htc_target *target, struct htc_endpoint *pEndpoint, HTC_TX_TAG Tag) +{ + struct htc_packet *pPacket; + struct htc_packet_queue discardQueue; + struct htc_packet_queue container; + + /* initialize the discard queue */ + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HTC_TX(target); + + /* interate from the front of the TX queue and flush out packets */ + ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, struct htc_packet, ListLink) { + + /* check for removal */ + if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) { + /* remove from queue */ + HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket); + /* add it to the discard pile */ + HTC_PACKET_ENQUEUE(&discardQueue, pPacket); + } + + } ITERATE_END; + + UNLOCK_HTC_TX(target); + + /* empty the discard queue */ + while (1) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + if (NULL == pPacket) { + break; + } + pPacket->Status = A_ECANCELED; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%lX, length:%d, ep:%d tag:0x%X \n", + (unsigned long)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + DO_EP_TX_COMPLETION(pEndpoint,&container); + } + +} + +void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", + pEPDist->Endpoint, pEPDist->ServiceID)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%lX next:0x%lX prev:0x%lX\n", + (unsigned long)pEPDist, (unsigned long)pEPDist->pNext, (unsigned long)pEPDist->pPrev)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", + HTC_PACKET_QUEUE_DEPTH(&((struct htc_endpoint *)pEPDist->pHTCReserved)->TxQueue))); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); +} + +void DumpCreditDistStates(struct htc_target *target) +{ + struct htc_endpoint_credit_dist *pEPList = target->EpCreditDistributionListHead; + + while (pEPList != NULL) { + DumpCreditDist(pEPList); + pEPList = pEPList->pNext; + } + + if (target->DistributeCredits != NULL) { + DO_DISTRIBUTION(target, + HTC_DUMP_CREDIT_STATE, + "Dump State", + NULL); + } +} + +/* flush all send packets from all endpoint queues */ +void HTCFlushSendPkts(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { + DumpCreditDistStates(target); + } + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID == 0) { + /* not in use.. */ + continue; + } + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); + } + + +} + +/* HTC API to flush an endpoint's TX queue*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + + if (pEndpoint->ServiceID == 0) { + AR_DEBUG_ASSERT(false); + /* not in use.. */ + return; + } + + HTCFlushEndpointTX(target, pEndpoint, Tag); +} + +/* HTC API to indicate activity to the credit distribution function */ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + bool Active) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + bool doDist = false; + + if (pEndpoint->ServiceID == 0) { + AR_DEBUG_ASSERT(false); + /* not in use.. */ + return; + } + + LOCK_HTC_TX(target); + + if (Active) { + if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) { + /* mark active now */ + pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE; + doDist = true; + } + } else { + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) { + /* mark inactive now */ + pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE; + doDist = true; + } + } + + if (doDist) { + /* indicate current Tx Queue depth to the credit distribution function */ + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + /* do distribution again based on activity change + * note, this is done with the lock held */ + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_ACTIVITY_CHANGE, + "Activity Change", + target->EpCreditDistributionListHead->pNext); + } + + UNLOCK_HTC_TX(target); + + if (doDist && !Active) { + /* if a stream went inactive and this resulted in a credit distribution change, + * some credits may now be available for HTC packets that are stuck in + * HTC queues */ + HTCCheckEndpointTxQueues(target); + } +} + +bool HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + + if (pEndpoint->ServiceID == 0) { + return false; + } + + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) { + return true; + } + + return false; +} diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_services.c b/trunk/drivers/staging/ath6kl/htc2/htc_services.c new file mode 100644 index 000000000000..c48070cbd54f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_services.c @@ -0,0 +1,450 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +void HTCControlTxComplete(void *Context, struct htc_packet *pPacket) +{ + /* not implemented + * we do not send control TX frames during normal runtime, only during setup */ + AR_DEBUG_ASSERT(false); +} + + /* callback when a control message arrives on this endpoint */ +void HTCControlRecv(void *Context, struct htc_packet *pPacket) +{ + AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0); + + if (pPacket->Status == A_ECANCELED) { + /* this is a flush operation, return the control packet back to the pool */ + HTC_FREE_CONTROL_RX((struct htc_target*)Context,pPacket); + return; + } + + /* the only control messages we are expecting are NULL messages (credit resports) */ + if (pPacket->ActualLength > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCControlRecv, got message with length:%d \n", + pPacket->ActualLength + (u32)HTC_HDR_LENGTH)); + +#ifdef ATH_DEBUG_MODULE + /* dump header and message */ + DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH, + pPacket->ActualLength + HTC_HDR_LENGTH, + "Unexpected ENDPOINT 0 Message"); +#endif + } + + HTC_RECYCLE_RX_PKT((struct htc_target*)Context,pPacket,&((struct htc_target*)Context)->EndPoint[0]); +} + +int HTCSendSetupComplete(struct htc_target *target) +{ + struct htc_packet *pSendPacket = NULL; + int status; + + do { + /* allocate a packet to send to the target */ + pSendPacket = HTC_ALLOC_CONTROL_TX(target); + + if (NULL == pSendPacket) { + status = A_NO_MEMORY; + break; + } + + if (target->HTCTargetVersion >= HTC_VERSION_2P1) { + HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx; + u32 setupFlags = 0; + + pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer; + A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); + pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID; + if (target->MaxMsgPerBundle > 0) { + /* host can do HTC bundling, indicate this to the target */ + setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; + pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle; + } + memcpy(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags)); + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pSetupCompleteEx, + sizeof(HTC_SETUP_COMPLETE_EX_MSG), + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + } else { + HTC_SETUP_COMPLETE_MSG *pSetupComplete; + /* assemble setup complete message */ + pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; + A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG)); + pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pSetupComplete, + sizeof(HTC_SETUP_COMPLETE_MSG), + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + } + + /* we want synchronous operation */ + pSendPacket->Completion = NULL; + HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); + /* send the message */ + status = HTCIssueSend(target,pSendPacket); + + } while (false); + + if (pSendPacket != NULL) { + HTC_FREE_CONTROL_TX(target,pSendPacket); + } + + return status; +} + + +int HTCConnectService(HTC_HANDLE HTCHandle, + struct htc_service_connect_req *pConnectReq, + struct htc_service_connect_resp *pConnectResp) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int status = 0; + struct htc_packet *pRecvPacket = NULL; + struct htc_packet *pSendPacket = NULL; + HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; + HTC_CONNECT_SERVICE_MSG *pConnectMsg; + HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; + struct htc_endpoint *pEndpoint; + unsigned int maxMsgSize = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n", + (unsigned long)target, pConnectReq->ServiceID)); + + do { + + AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); + + if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { + /* special case for pseudo control service */ + assignedEndpoint = ENDPOINT_0; + maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; + } else { + /* allocate a packet to send to the target */ + pSendPacket = HTC_ALLOC_CONTROL_TX(target); + + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(false); + status = A_NO_MEMORY; + break; + } + /* assemble connect service message */ + pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; + AR_DEBUG_ASSERT(pConnectMsg != NULL); + A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); + pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; + pConnectMsg->ServiceID = pConnectReq->ServiceID; + pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; + /* check caller if it wants to transfer meta data */ + if ((pConnectReq->pMetaData != NULL) && + (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* copy meta data into message buffer (after header ) */ + memcpy((u8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), + pConnectReq->pMetaData, + pConnectReq->MetaDataLength); + pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; + } + + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pConnectMsg, + sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + /* we want synchronous operation */ + pSendPacket->Completion = NULL; + HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); + status = HTCIssueSend(target,pSendPacket); + + if (status) { + break; + } + + /* wait for response */ + status = HTCWaitforControlMessage(target, &pRecvPacket); + + if (status) { + break; + } + /* we controlled the buffer creation so it has to be properly aligned */ + pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; + + if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || + (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + pConnectResp->ConnectRespCode = pResponseMsg->Status; + /* check response status */ + if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Target failed service 0x%X connect request (status:%d)\n", + pResponseMsg->ServiceID, pResponseMsg->Status)); + status = A_EPROTO; + break; + } + + assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID; + maxMsgSize = pResponseMsg->MaxMsgSize; + + if ((pConnectResp->pMetaData != NULL) && + (pResponseMsg->ServiceMetaLength > 0) && + (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* caller supplied a buffer and the target responded with data */ + int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); + /* copy the meta data */ + memcpy(pConnectResp->pMetaData, + ((u8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), + copyLength); + pConnectResp->ActualLength = copyLength; + } + + } + + /* the rest of these are parameter checks so set the error status */ + status = A_EPROTO; + + if (assignedEndpoint >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(false); + break; + } + + if (0 == maxMsgSize) { + AR_DEBUG_ASSERT(false); + break; + } + + pEndpoint = &target->EndPoint[assignedEndpoint]; + pEndpoint->Id = assignedEndpoint; + if (pEndpoint->ServiceID != 0) { + /* endpoint already in use! */ + AR_DEBUG_ASSERT(false); + break; + } + + /* return assigned endpoint to caller */ + pConnectResp->Endpoint = assignedEndpoint; + pConnectResp->MaxMsgLength = maxMsgSize; + + /* setup the endpoint */ + pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ + pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; + pEndpoint->MaxMsgLength = maxMsgSize; + /* copy all the callbacks */ + pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; + /* set the credit distribution info for this endpoint, this information is + * passed back to the credit distribution callback function */ + pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; + pEndpoint->CreditDist.pHTCReserved = pEndpoint; + pEndpoint->CreditDist.Endpoint = assignedEndpoint; + pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; + + if (pConnectReq->MaxSendMsgSize != 0) { + /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications + * since the host will actually issue smaller messages in the Send path */ + if (pConnectReq->MaxSendMsgSize > maxMsgSize) { + /* can't be larger than the maximum the target can support */ + AR_DEBUG_ASSERT(false); + break; + } + pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize; + } else { + pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; + } + + if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; + } + + /* save local connection flags */ + pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags; + + status = 0; + + } while (false); + + if (pSendPacket != NULL) { + HTC_FREE_CONTROL_TX(target,pSendPacket); + } + + if (pRecvPacket != NULL) { + HTC_FREE_CONTROL_RX(target,pRecvPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); + + return status; +} + +static void AddToEndpointDistList(struct htc_target *target, struct htc_endpoint_credit_dist *pEpDist) +{ + struct htc_endpoint_credit_dist *pCurEntry,*pLastEntry; + + if (NULL == target->EpCreditDistributionListHead) { + target->EpCreditDistributionListHead = pEpDist; + pEpDist->pNext = NULL; + pEpDist->pPrev = NULL; + return; + } + + /* queue to the end of the list, this does not have to be very + * fast since this list is built at startup time */ + pCurEntry = target->EpCreditDistributionListHead; + + while (pCurEntry) { + pLastEntry = pCurEntry; + pCurEntry = pCurEntry->pNext; + } + + pLastEntry->pNext = pEpDist; + pEpDist->pPrev = pLastEntry; + pEpDist->pNext = NULL; +} + + + +/* default credit init callback */ +static void HTCDefaultCreditInit(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int totalEps = 0; + int creditsPerEndpoint; + + pCurEpDist = pEPList; + /* first run through the list and figure out how many endpoints we are dealing with */ + while (pCurEpDist != NULL) { + pCurEpDist = pCurEpDist->pNext; + totalEps++; + } + + /* even distribution */ + creditsPerEndpoint = TotalCredits/totalEps; + + pCurEpDist = pEPList; + /* run through the list and set minimum and normal credits and + * provide the endpoint with some credits to start */ + while (pCurEpDist != NULL) { + + if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) { + /* too many endpoints and not enough credits */ + AR_DEBUG_ASSERT(false); + break; + } + /* our minimum is set for at least 1 max message */ + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; + /* this value is ignored by our credit alg, since we do + * not dynamically adjust credits, this is the policy of + * the "default" credit distribution, something simple and easy */ + pCurEpDist->TxCreditsNorm = 0xFFFF; + /* give the endpoint minimum credits */ + pCurEpDist->TxCredits = creditsPerEndpoint; + pCurEpDist->TxCreditsAssigned = creditsPerEndpoint; + pCurEpDist = pCurEpDist->pNext; + } + +} + +/* default credit distribution callback, NOTE, this callback holds the TX lock */ +void HTCDefaultCreditDist(void *Context, + struct htc_endpoint_credit_dist *pEPDistList, + HTC_CREDIT_DIST_REASON Reason) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + + if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) { + pCurEpDist = pEPDistList; + /* simple distribution */ + while (pCurEpDist != NULL) { + if (pCurEpDist->TxCreditsToDist > 0) { + /* just give the endpoint back the credits */ + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; + pCurEpDist->TxCreditsToDist = 0; + } + pCurEpDist = pCurEpDist->pNext; + } + } + + /* note we do not need to handle the other reason codes as this is a very + * simple distribution scheme, no need to seek for more credits or handle inactivity */ +} + +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + int ep; + + if (CreditInitFunc != NULL) { + /* caller has supplied their own distribution functions */ + target->InitCredits = CreditInitFunc; + AR_DEBUG_ASSERT(CreditDistFunc != NULL); + target->DistributeCredits = CreditDistFunc; + target->pCredDistContext = pCreditDistContext; + } else { + /* caller wants HTC to do distribution */ + /* if caller wants service to handle distributions then + * it must set both of these to NULL! */ + AR_DEBUG_ASSERT(CreditDistFunc == NULL); + target->InitCredits = HTCDefaultCreditInit; + target->DistributeCredits = HTCDefaultCreditDist; + target->pCredDistContext = target; + } + + /* always add HTC control endpoint first, we only expose the list after the + * first one, this is added for TX queue checking */ + AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist); + + /* build the list of credit distribution structures in priority order + * supplied by the caller, these will follow endpoint 0 */ + for (i = 0; i < ListLength; i++) { + /* match services with endpoints and add the endpoints to the distribution list + * in FIFO order */ + for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { + if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) { + /* queue this one to the list */ + AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist); + break; + } + } + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); + } + +} diff --git a/trunk/drivers/staging/ath6kl/include/a_config.h b/trunk/drivers/staging/ath6kl/include/a_config.h new file mode 100644 index 000000000000..f7c09319433f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_config.h @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains software configuration options that enables +// specific software "features" +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_CONFIG_H_ +#define _A_CONFIG_H_ + +#include "../os/linux/include/config_linux.h" + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_debug.h b/trunk/drivers/staging/ath6kl/include/a_debug.h new file mode 100644 index 000000000000..5154fcb1ca64 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_debug.h @@ -0,0 +1,195 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DEBUG_H_ +#define _A_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + + /* standard debug print masks bits 0..7 */ +#define ATH_DEBUG_ERR (1 << 0) /* errors */ +#define ATH_DEBUG_WARN (1 << 1) /* warnings */ +#define ATH_DEBUG_INFO (1 << 2) /* informational (module startup info) */ +#define ATH_DEBUG_TRC (1 << 3) /* generic function call tracing */ +#define ATH_DEBUG_RSVD1 (1 << 4) +#define ATH_DEBUG_RSVD2 (1 << 5) +#define ATH_DEBUG_RSVD3 (1 << 6) +#define ATH_DEBUG_RSVD4 (1 << 7) + +#define ATH_DEBUG_MASK_DEFAULTS (ATH_DEBUG_ERR | ATH_DEBUG_WARN) +#define ATH_DEBUG_ANY 0xFFFF + + /* other aliases used throughout */ +#define ATH_DEBUG_ERROR ATH_DEBUG_ERR +#define ATH_LOG_ERR ATH_DEBUG_ERR +#define ATH_LOG_INF ATH_DEBUG_INFO +#define ATH_LOG_TRC ATH_DEBUG_TRC +#define ATH_DEBUG_TRACE ATH_DEBUG_TRC +#define ATH_DEBUG_INIT ATH_DEBUG_INFO + + /* bits 8..31 are module-specific masks */ +#define ATH_DEBUG_MODULE_MASK_SHIFT 8 + + /* macro to make a module-specific masks */ +#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index))) + +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription); + +/* Debug support on a per-module basis + * + * Usage: + * + * Each module can utilize it's own debug mask variable. A set of commonly used + * masks are provided (ERRORS, WARNINGS, TRACE etc..). It is up to each module + * to define module-specific masks using the macros above. + * + * Each module defines a single debug mask variable debug_XXX where the "name" of the module is + * common to all C-files within that module. This requires every C-file that includes a_debug.h + * to define the module name in that file. + * + * Example: + * + * #define ATH_MODULE_NAME htc + * #include "a_debug.h" + * + * This will define a debug mask structure called debug_htc and all debug macros will reference this + * variable. + * + * A module can define module-specific bit masks using the ATH_DEBUG_MAKE_MODULE_MASK() macro: + * + * #define ATH_DEBUG_MY_MASK1 ATH_DEBUG_MAKE_MODULE_MASK(0) + * #define ATH_DEBUG_MY_MASK2 ATH_DEBUG_MAKE_MODULE_MASK(1) + * + * The instantiation of the debug structure should be made by the module. When a module is + * instantiated, the module can set a description string, a default mask and an array of description + * entries containing information on each module-defined debug mask. + * NOTE: The instantiation is statically allocated, only one instance can exist per module. + * + * Example: + * + * + * #define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + * + * #ifdef DEBUG + * static struct ath_debug_mask_description bmi_debug_desc[] = { + * { ATH_DEBUG_BMI , "BMI Tracing"}, <== description of the module specific mask + * }; + * + * ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + * "bmi" <== module name + * "Boot Manager Interface", <== description of module + * ATH_DEBUG_MASK_DEFAULTS, <== defaults + * ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + * bmi_debug_desc); + * + * #endif + * + * A module can optionally register it's debug module information in order for other tools to change the + * bit mask at runtime. A module can call A_REGISTER_MODULE_DEBUG_INFO() in it's module + * init code. This macro can be called multiple times without consequence. The debug info maintains + * state to indicate whether the information was previously registered. + * + * */ + +#define ATH_DEBUG_MAX_MASK_DESC_LENGTH 32 +#define ATH_DEBUG_MAX_MOD_DESC_LENGTH 64 + +struct ath_debug_mask_description { + u32 Mask; + char Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH]; +}; + +#define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0) + +typedef struct _ATH_DEBUG_MODULE_DBG_INFO{ + struct _ATH_DEBUG_MODULE_DBG_INFO *pNext; + char ModuleName[16]; + char ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH]; + u32 Flags; + u32 CurrentMask; + int MaxDescriptions; + struct ath_debug_mask_description *pMaskDescriptions; /* pointer to array of descriptions */ +} ATH_DEBUG_MODULE_DBG_INFO; + +#define ATH_DEBUG_DESCRIPTION_COUNT(d) (int)((sizeof((d))) / (sizeof(struct ath_debug_mask_description))) + +#define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s) +#define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask +#define _XGET_ATH_MODULE_NAME_DEBUG_(s) debug_ ## s + +#ifdef ATH_DEBUG_MODULE + + /* for source files that will instantiate the debug variables */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) \ +ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) = \ + {NULL,(name),(moddesc),0,(initmask),count,(descriptions)} + +#ifdef ATH_MODULE_NAME +extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(ATH_MODULE_NAME); +#define AR_DEBUG_LVL_CHECK(lvl) (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (lvl)) +#endif /* ATH_MODULE_NAME */ + +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) GET_ATH_MODULE_DEBUG_VAR_MASK(s) = (lvl) + +#define ATH_DEBUG_DECLARE_EXTERN(s) \ + extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) + +#define AR_DEBUG_PRINTBUF(buffer, length, desc) DebugDumpBytes(buffer,length,desc) + + +#define AR_DEBUG_ASSERT A_ASSERT + +void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +#define A_DUMP_MODULE_DEBUG_INFO(s) a_dump_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) +#define A_REGISTER_MODULE_DEBUG_INFO(s) a_register_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) + +#else /* !ATH_DEBUG_MODULE */ + /* NON ATH_DEBUG_MODULE */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) +#define AR_DEBUG_LVL_CHECK(lvl) 0 +#define AR_DEBUG_PRINTBUF(buffer, length, desc) +#define AR_DEBUG_ASSERT(test) +#define ATH_DEBUG_DECLARE_EXTERN(s) +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) +#define A_DUMP_MODULE_DEBUG_INFO(s) +#define A_REGISTER_MODULE_DEBUG_INFO(s) + +#endif + +int a_get_module_mask(char *module_name, u32 *pMask); +int a_set_module_mask(char *module_name, u32 Mask); +void a_dump_module_debug_info_by_name(char *module_name); +void a_module_debug_support_init(void); +void a_module_debug_support_cleanup(void); + +#include "../os/linux/include/debug_linux.h" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_drv.h b/trunk/drivers/staging/ath6kl/include/a_drv.h new file mode 100644 index 000000000000..1548604e8465 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_drv.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DRV_H_ +#define _A_DRV_H_ + +#include "../os/linux/include/athdrv_linux.h" + +#endif /* _ADRV_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/a_drv_api.h b/trunk/drivers/staging/ath6kl/include/a_drv_api.h new file mode 100644 index 000000000000..a40d97a84ffc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_drv_api.h @@ -0,0 +1,204 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DRV_API_H_ +#define _A_DRV_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** WMI related hooks **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ + +#include + +#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \ + ar6000_channelList_rx((devt), (numChan), (chanList)) + +#define A_WMI_SET_NUMDATAENDPTS(devt, num) \ + ar6000_set_numdataendpts((devt), (num)) + +#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \ + ar6000_control_tx((devt), (osbuf), (streamID)) + +#define A_WMI_TARGETSTATS_EVENT(devt, pStats, len) \ + ar6000_targetStats_event((devt), (pStats), (len)) + +#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \ + ar6000_scanComplete_event((devt), (status)) + +#ifdef CONFIG_HOST_DSET_SUPPORT + +#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \ + ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg)) + +#define A_WMI_DSET_CLOSE(devt, access_cookie) \ + ar6000_dset_close((devt), (access_cookie)) + +#endif + +#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \ + ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg)) + +#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \ + ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo)) + +#define A_WMI_PSPOLL_EVENT(devt, aid)\ + ar6000_pspoll_event((devt),(aid)) + +#define A_WMI_DTIMEXPIRY_EVENT(devt)\ + ar6000_dtimexpiry_event((devt)) + +#ifdef WAPI_ENABLE +#define A_WMI_WAPI_REKEY_EVENT(devt, type, mac)\ + ap_wapi_rekey_event((devt),(type),(mac)) +#endif + +#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \ + ar6000_regDomain_event((devt), (regCode)) + +#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \ + ar6000_neighborReport_event((devt), (numAps), (info)) + +#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \ + ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus)) + +#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \ + ar6000_tkip_micerr_event((devt), (keyid), (ismcast)) + +#define A_WMI_BITRATE_RX(devt, rateKbps) \ + ar6000_bitrate_rx((devt), (rateKbps)) + +#define A_WMI_TXPWR_RX(devt, txPwr) \ + ar6000_txPwr_rx((devt), (txPwr)) + +#define A_WMI_READY_EVENT(devt, datap, phyCap, sw_ver, abi_ver) \ + ar6000_ready_event((devt), (datap), (phyCap), (sw_ver), (abi_ver)) + +#define A_WMI_DBGLOG_INIT_DONE(ar) \ + ar6000_dbglog_init_done(ar); + +#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \ + ar6000_rssiThreshold_event((devt), (newThreshold), (rssi)) + +#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \ + ar6000_reportError_event((devt), (errorVal)) + +#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \ + ar6000_roam_tbl_event((devt), (pTbl)) + +#define A_WMI_ROAM_DATA_EVENT(devt, p) \ + ar6000_roam_data_event((devt), (p)) + +#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \ + ar6000_wow_list_event((devt), (num_filters), (wow_filters)) + +#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \ + ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion)) + +#define A_WMI_CHANNEL_CHANGE_EVENT(devt, oldChannel, newChannel) \ + ar6000_channel_change_event((devt), (oldChannel), (newChannel)) + +#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list, bssid_list) \ + ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list), (bssid_list)) + +#define A_WMI_PEER_EVENT(devt, eventCode, bssid) \ + ar6000_peer_event ((devt), (eventCode), (bssid)) + +#ifdef CONFIG_HOST_TCMD_SUPPORT +#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \ + ar6000_tcmd_rx_report_event((devt), (results), (len)) +#endif + +#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \ + ar6000_hbChallengeResp_event((devt), (cookie), (source)) + +#define A_WMI_TX_RETRY_ERR_EVENT(devt) \ + ar6000_tx_retry_err_event((devt)) + +#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \ + ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr)) + +#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \ + ar6000_lqThresholdEvent_rx((devt), (range), (lqVal)) + +#define A_WMI_RATEMASK_RX(devt, ratemask) \ + ar6000_ratemask_rx((devt), (ratemask)) + +#define A_WMI_KEEPALIVE_RX(devt, configured) \ + ar6000_keepalive_rx((devt), (configured)) + +#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \ + ar6000_bssInfo_event_rx((ar), (datap), (len)) + +#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \ + ar6000_dbglog_event((ar), (dropped), (buffer), (length)); + +#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \ + ar6000_indicate_tx_activity((devt),(trafficClass), true) + +#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \ + ar6000_indicate_tx_activity((devt),(trafficClass), false) +#define A_WMI_Ac2EndpointID(devht, ac)\ + ar6000_ac2_endpoint_id((devht), (ac)) + +#define A_WMI_AGGR_RECV_ADDBA_REQ_EVT(devt, cmd)\ + ar6000_aggr_rcv_addba_req_evt((devt), (cmd)) +#define A_WMI_AGGR_RECV_ADDBA_RESP_EVT(devt, cmd)\ + ar6000_aggr_rcv_addba_resp_evt((devt), (cmd)) +#define A_WMI_AGGR_RECV_DELBA_REQ_EVT(devt, cmd)\ + ar6000_aggr_rcv_delba_req_evt((devt), (cmd)) +#define A_WMI_HCI_EVENT_EVT(devt, cmd)\ + ar6000_hci_event_rcv_evt((devt), (cmd)) + +#define A_WMI_Endpoint2Ac(devt, ep) \ + ar6000_endpoint_id2_ac((devt), (ep)) + +#define A_WMI_BTCOEX_CONFIG_EVENT(devt, evt, len)\ + ar6000_btcoex_config_event((devt), (evt), (len)) + +#define A_WMI_BTCOEX_STATS_EVENT(devt, datap, len)\ + ar6000_btcoex_stats_event((devt), (datap), (len)) + +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** HTC related hooks **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +#define A_WMI_PROF_COUNT_RX(addr, count) prof_count_rx((addr), (count)) +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_osapi.h b/trunk/drivers/staging/ath6kl/include/a_osapi.h new file mode 100644 index 000000000000..fd7ae0d612c6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_osapi.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_OSAPI_H_ +#define _A_OSAPI_H_ + +#include "../os/linux/include/osapi_linux.h" + +#endif /* _OSAPI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h b/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h new file mode 100644 index 000000000000..5ead58d5febd --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h @@ -0,0 +1,140 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +#ifndef __AGGR_RECV_API_H__ +#define __AGGR_RECV_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (* RX_CALLBACK)(void * dev, void *osbuf); + +typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, u16 num); + +/* + * aggr_init: + * Initialises the data structures, allocates data queues and + * os buffers. Netbuf allocator is the input param, used by the + * aggr module for allocation of NETBUFs from driver context. + * These NETBUFs are used for AMSDU processing. + * Returns the context for the aggr module. + */ +void * +aggr_init(ALLOC_NETBUFS netbuf_allocator); + + +/* + * aggr_register_rx_dispatcher: + * Registers OS call back function to deliver the + * frames to OS. This is generally the topmost layer of + * the driver context, after which the frames go to + * IP stack via the call back function. + * This dispatcher is active only when aggregation is ON. + */ +void +aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn); + + +/* + * aggr_process_bar: + * When target receives BAR, it communicates to host driver + * for modifying window parameters. Target indicates this via the + * event: WMI_ADDBA_REQ_EVENTID. Host will dequeue all frames + * up to the indicated sequence number. + */ +void +aggr_process_bar(void *cntxt, u8 tid, u16 seq_no); + + +/* + * aggr_recv_addba_req_evt: + * This event is to initiate/modify the receive side window. + * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup + * recv re-ordering queues. Target will negotiate ADDBA with peer, + * and indicate via this event after successfully completing the + * negotiation. This happens in two situations: + * 1. Initial setup of aggregation + * 2. Renegotiation of current recv window. + * Window size for re-ordering is limited by target buffer + * space, which is reflected in win_sz. + * (Re)Start the periodic timer to deliver long standing frames, + * in hold_q to OS. + */ +void +aggr_recv_addba_req_evt(void * cntxt, u8 tid, u16 seq_no, u8 win_sz); + + +/* + * aggr_recv_delba_req_evt: + * Target indicates deletion of a BA window for a tid via the + * WMI_DELBA_EVENTID. Host would deliver all the frames in the + * hold_q, reset tid config and disable the periodic timer, if + * aggr is not enabled on any tid. + */ +void +aggr_recv_delba_req_evt(void * cntxt, u8 tid); + + + +/* + * aggr_process_recv_frm: + * Called only for data frames. When aggr is ON for a tid, the buffer + * is always consumed, and osbuf would be NULL. For a non-aggr case, + * osbuf is not modified. + * AMSDU frames are consumed and are later freed. They are sliced and + * diced to individual frames and dispatched to stack. + * After consuming a osbuf(when aggr is ON), a previously registered + * callback may be called to deliver frames in order. + */ +void +aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf); + + +/* + * aggr_module_destroy: + * Frees up all the queues and frames in them. Releases the cntxt to OS. + */ +void +aggr_module_destroy(void *cntxt); + +/* + * Dumps the aggregation stats + */ +void +aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf); + +/* + * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate + * hold Q state. Examples include when a Connect event or disconnect event is + * received. + */ +void +aggr_reset_state(void *cntxt); + + +#ifdef __cplusplus +} +#endif + +#endif /*__AGGR_RECV_API_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/ar3kconfig.h b/trunk/drivers/staging/ath6kl/include/ar3kconfig.h new file mode 100644 index 000000000000..91bc4ee3512d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar3kconfig.h @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* AR3K module configuration APIs for HCI-bridge operation */ + +#ifndef AR3KCONFIG_H_ +#define AR3KCONFIG_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT (1 << 0) +#define AR3K_CONFIG_FLAG_SET_AR3K_BAUD (1 << 1) +#define AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY (1 << 2) +#define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP (1 << 3) + + +struct ar3k_config_info { + u32 Flags; /* config flags */ + void *pHCIDev; /* HCI bridge device */ + struct hci_transport_properties *pHCIProps; /* HCI bridge props */ + struct hif_device *pHIFDevice; /* HIF layer device */ + + u32 AR3KBaudRate; /* AR3K operational baud rate */ + u16 AR6KScale; /* AR6K UART scale value */ + u16 AR6KStep; /* AR6K UART step value */ + struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */ + u32 PwrMgmtEnabled; /* TLPM enabled? */ + u16 IdleTimeout; /* TLPM idle timeout */ + u16 WakeupTimeout; /* TLPM wakeup timeout */ + u8 bdaddr[6]; /* Bluetooth device address */ +}; + +int AR3KConfigure(struct ar3k_config_info *pConfigInfo); + +int AR3KConfigureExit(void *config); + +#ifdef __cplusplus +} +#endif + +#endif /*AR3KCONFIG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/ar6000_api.h b/trunk/drivers/staging/ath6kl/include/ar6000_api.h new file mode 100644 index 000000000000..e9460800272c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6000_api.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the API to access the OS dependent atheros host driver +// by the WMI or WLAN generic modules. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _AR6000_API_H_ +#define _AR6000_API_H_ + +#include "../os/linux/include/ar6xapi_linux.h" + +#endif /* _AR6000_API_H */ + diff --git a/trunk/drivers/staging/ath6kl/include/ar6000_diag.h b/trunk/drivers/staging/ath6kl/include/ar6000_diag.h new file mode 100644 index 000000000000..739c01c53f08 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6000_diag.h @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef AR6000_DIAG_H_ +#define AR6000_DIAG_H_ + + +int +ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int +ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int +ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length); + +int +ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length); + +int +ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval); + +void +ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs); + +#endif /*AR6000_DIAG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/ar6kap_common.h b/trunk/drivers/staging/ath6kl/include/ar6kap_common.h new file mode 100644 index 000000000000..532d8eba9326 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6kap_common.h @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ + +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ + +//============================================================================== + +// This file contains the definitions of common AP mode data structures. +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _AR6KAP_COMMON_H_ +#define _AR6KAP_COMMON_H_ +/* + * Used with AR6000_XIOCTL_AP_GET_STA_LIST + */ +typedef struct { + u8 mac[ATH_MAC_LEN]; + u8 aid; + u8 keymgmt; + u8 ucipher; + u8 auth; +} station_t; +typedef struct { + station_t sta[AP_MAX_NUM_STA]; +} ap_get_sta_t; +#endif /* _AR6KAP_COMMON_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/athbtfilter.h b/trunk/drivers/staging/ath6kl/include/athbtfilter.h new file mode 100644 index 000000000000..81456eea3b0b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/athbtfilter.h @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Public Bluetooth filter APIs +// Author(s): ="Atheros" +//============================================================================== +#ifndef ATHBTFILTER_H_ +#define ATHBTFILTER_H_ + +#define ATH_DEBUG_INFO (1 << 2) +#define ATH_DEBUG_INF ATH_DEBUG_INFO + +typedef enum _ATHBT_HCI_CTRL_TYPE { + ATHBT_HCI_COMMAND = 0, + ATHBT_HCI_EVENT = 1, +} ATHBT_HCI_CTRL_TYPE; + +typedef enum _ATHBT_STATE_INDICATION { + ATH_BT_NOOP = 0, + ATH_BT_INQUIRY = 1, + ATH_BT_CONNECT = 2, + ATH_BT_SCO = 3, + ATH_BT_ACL = 4, + ATH_BT_A2DP = 5, + ATH_BT_ESCO = 6, + /* new states go here.. */ + + ATH_BT_MAX_STATE_INDICATION +} ATHBT_STATE_INDICATION; + + /* filter function for OUTGOING commands and INCOMMING events */ +typedef void (*ATHBT_FILTER_CMD_EVENTS_FN)(void *pContext, ATHBT_HCI_CTRL_TYPE Type, unsigned char *pBuffer, int Length); + + /* filter function for OUTGOING data HCI packets */ +typedef void (*ATHBT_FILTER_DATA_FN)(void *pContext, unsigned char *pBuffer, int Length); + +typedef enum _ATHBT_STATE { + STATE_OFF = 0, + STATE_ON = 1, + STATE_MAX +} ATHBT_STATE; + + /* BT state indication (when filter functions are not used) */ + +typedef void (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion); + +struct athbt_filter_instance { +#ifdef UNDER_CE + WCHAR *pWlanAdapterName; /* filled in by user */ +#else + char *pWlanAdapterName; /* filled in by user */ +#endif /* UNDER_CE */ + int FilterEnabled; /* filtering is enabled */ + int Attached; /* filter library is attached */ + void *pContext; /* private context for filter library */ + ATHBT_FILTER_CMD_EVENTS_FN pFilterCmdEvents; /* function ptr to filter a command or event */ + ATHBT_FILTER_DATA_FN pFilterAclDataOut; /* function ptr to filter ACL data out (to radio) */ + ATHBT_FILTER_DATA_FN pFilterAclDataIn; /* function ptr to filter ACL data in (from radio) */ + ATHBT_INDICATE_STATE_FN pIndicateState; /* function ptr to indicate a state */ +}; /* XXX: unused ? */ + + +/* API MACROS */ + +#define AthBtFilterHciCommand(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterCmdEvents((instance)->pContext, \ + ATHBT_HCI_COMMAND, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciEvent(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterCmdEvents((instance)->pContext, \ + ATHBT_HCI_EVENT, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciAclDataOut(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterAclDataOut((instance)->pContext, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciAclDataIn(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterAclDataIn((instance)->pContext, \ + (unsigned char *)(packet), \ + (length)); \ + } + +/* if filtering is not desired, the application can indicate the state directly using this + * macro: + */ +#define AthBtIndicateState(instance,indication,state) \ + if ((instance)->FilterEnabled) { \ + (instance)->pIndicateState((instance)->pContext, \ + (indication), \ + (state), \ + 0); \ + } + +#ifdef __cplusplus +extern "C" { +#endif + +/* API prototypes */ +int AthBtFilter_Attach(ATH_BT_FILTER_INSTANCE *pInstance, unsigned int flags); +void AthBtFilter_Detach(ATH_BT_FILTER_INSTANCE *pInstance); + +#ifdef __cplusplus +} +#endif + +#endif /*ATHBTFILTER_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/bmi.h b/trunk/drivers/staging/ath6kl/include/bmi.h new file mode 100644 index 000000000000..d3227f77fa5d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/bmi.h @@ -0,0 +1,134 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// BMI declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _BMI_H_ +#define _BMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "a_config.h" +#include "athdefs.h" +#include "hif.h" +#include "a_osapi.h" +#include "bmi_msg.h" + +void +BMIInit(void); + +void +BMICleanup(void); + +int +BMIDone(struct hif_device *device); + +int +BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info); + +int +BMIReadMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIWriteMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIExecute(struct hif_device *device, + u32 address, + u32 *param); + +int +BMISetAppStart(struct hif_device *device, + u32 address); + +int +BMIReadSOCRegister(struct hif_device *device, + u32 address, + u32 *param); + +int +BMIWriteSOCRegister(struct hif_device *device, + u32 address, + u32 param); + +int +BMIrompatchInstall(struct hif_device *device, + u32 ROM_addr, + u32 RAM_addr, + u32 nbytes, + u32 do_activate, + u32 *patch_id); + +int +BMIrompatchUninstall(struct hif_device *device, + u32 rompatch_id); + +int +BMIrompatchActivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list); + +int +BMIrompatchDeactivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list); + +int +BMILZStreamStart(struct hif_device *device, + u32 address); + +int +BMILZData(struct hif_device *device, + u8 *buffer, + u32 length); + +int +BMIFastDownload(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIRawWrite(struct hif_device *device, + u8 *buffer, + u32 length); + +int +BMIRawRead(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* _BMI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h new file mode 100644 index 000000000000..5407e05d9b05 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#define __VER_MAJOR_ 3 +#define __VER_MINOR_ 0 +#define __VER_PATCH_ 0 + +/* The makear6ksdk script (used for release builds) modifies the following line. */ +#define __BUILD_NUMBER_ 233 + + +/* Format of the version number. */ +#define VER_MAJOR_BIT_OFFSET 28 +#define VER_MINOR_BIT_OFFSET 24 +#define VER_PATCH_BIT_OFFSET 16 +#define VER_BUILD_NUM_BIT_OFFSET 0 + + +/* + * The version has the following format: + * Bits 28-31: Major version + * Bits 24-27: Minor version + * Bits 16-23: Patch version + * Bits 0-15: Build number (automatically generated during build process ) + * E.g. Build 1.1.3.7 would be represented as 0x11030007. + * + * DO NOT split the following macro into multiple lines as this may confuse the build scripts. + */ +#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) ) + +/* ABI Version. Reflects the version of binary interface exposed by AR6K target firmware. Needs to be incremented by 1 for any change in the firmware that requires upgrade of the driver on the host side for the change to work correctly */ +#define AR6K_ABI_VERSION 1 diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h new file mode 100644 index 000000000000..bbf8d42828c1 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __ADDRS_H__ +#define __ADDRS_H__ + +/* + * Special AR6002 Addresses that may be needed by special + * applications (e.g. ART) on the Host as well as Target. + */ + +#if defined(AR6002_REV2) +#define AR6K_RAM_START 0x00500000 +#define TARG_RAM_OFFSET(vaddr) ((u32)(vaddr) & 0xfffff) +#define TARG_RAM_SZ (184*1024) +#define TARG_ROM_SZ (80*1024) +#endif +#if defined(AR6002_REV4) || defined(AR6003) +#define AR6K_RAM_START 0x00540000 +#define TARG_RAM_OFFSET(vaddr) (((u32)(vaddr) & 0xfffff) - 0x40000) +#define TARG_RAM_SZ (256*1024) +#define TARG_ROM_SZ (256*1024) +#endif + +#define AR6002_BOARD_DATA_SZ 768 +#define AR6002_BOARD_EXT_DATA_SZ 0 +#define AR6003_BOARD_DATA_SZ 1024 +#define AR6003_BOARD_EXT_DATA_SZ 768 + +#define AR6K_RAM_ADDR(byte_offset) (AR6K_RAM_START+(byte_offset)) +#define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset) + +#define AR6K_ROM_START 0x004e0000 +#define TARG_ROM_OFFSET(vaddr) (((u32)(vaddr) & 0x1fffff) - 0xe0000) +#define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset)) +#define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset) + +/* + * At this ROM address is a pointer to the start of the ROM DataSet Index. + * If there are no ROM DataSets, there's a 0 at this address. + */ +#define ROM_DATASET_INDEX_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-8) +#define ROM_MBIST_CKSUM_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-4) + +/* + * The API A_BOARD_DATA_ADDR() is the proper way to get a read pointer to + * board data. + */ + +/* Size of Board Data, in bytes */ +#if defined(AR6002_REV4) || defined(AR6003) +#define BOARD_DATA_SZ AR6003_BOARD_DATA_SZ +#else +#define BOARD_DATA_SZ AR6002_BOARD_DATA_SZ +#endif + + +/* + * Constants used by ASM code to access fields of host_interest_s, + * which is at a fixed location in RAM. + */ +#if defined(AR6002_REV4) || defined(AR6003) +#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x60c) +#else +#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x40c) +#endif +#define FLASH_IS_PRESENT_TARGADDR HOST_INTEREST_FLASH_IS_PRESENT_ADDR + +#endif /* __ADDRS_H__ */ + + + diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h new file mode 100644 index 000000000000..609eb9841f59 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _APB_ATHR_WLAN_MAP_H_ +#define _APB_ATHR_WLAN_MAP_H_ + +#define WLAN_RTC_BASE_ADDRESS 0x00004000 +#define WLAN_VMC_BASE_ADDRESS 0x00008000 +#define WLAN_UART_BASE_ADDRESS 0x0000c000 +#define WLAN_DBG_UART_BASE_ADDRESS 0x0000d000 +#define WLAN_UMBOX_BASE_ADDRESS 0x0000e000 +#define WLAN_SI_BASE_ADDRESS 0x00010000 +#define WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define WLAN_MBOX_BASE_ADDRESS 0x00018000 +#define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define WLAN_MAC_BASE_ADDRESS 0x00020000 +#define WLAN_RDMA_BASE_ADDRESS 0x00030100 +#define EFUSE_BASE_ADDRESS 0x00031000 + +#endif /* _APB_ATHR_WLAN_MAP_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h new file mode 100644 index 000000000000..0068ca31b051 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "apb_athr_wlan_map.h" + +#ifndef BT_HEADERS + +#define RTC_BASE_ADDRESS WLAN_RTC_BASE_ADDRESS +#define VMC_BASE_ADDRESS WLAN_VMC_BASE_ADDRESS +#define UART_BASE_ADDRESS WLAN_UART_BASE_ADDRESS +#define DBG_UART_BASE_ADDRESS WLAN_DBG_UART_BASE_ADDRESS +#define UMBOX_BASE_ADDRESS WLAN_UMBOX_BASE_ADDRESS +#define SI_BASE_ADDRESS WLAN_SI_BASE_ADDRESS +#define GPIO_BASE_ADDRESS WLAN_GPIO_BASE_ADDRESS +#define MBOX_BASE_ADDRESS WLAN_MBOX_BASE_ADDRESS +#define ANALOG_INTF_BASE_ADDRESS WLAN_ANALOG_INTF_BASE_ADDRESS +#define MAC_BASE_ADDRESS WLAN_MAC_BASE_ADDRESS +#define RDMA_BASE_ADDRESS WLAN_RDMA_BASE_ADDRESS + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h new file mode 100644 index 000000000000..109f24e10a65 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "mbox_wlan_host_reg.h" diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h new file mode 100644 index 000000000000..72fa483450d6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h @@ -0,0 +1,552 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "mbox_wlan_reg.h" + +#ifndef BT_HEADERS + +#define MBOX_FIFO_ADDRESS WLAN_MBOX_FIFO_ADDRESS +#define MBOX_FIFO_OFFSET WLAN_MBOX_FIFO_OFFSET +#define MBOX_FIFO_DATA_MSB WLAN_MBOX_FIFO_DATA_MSB +#define MBOX_FIFO_DATA_LSB WLAN_MBOX_FIFO_DATA_LSB +#define MBOX_FIFO_DATA_MASK WLAN_MBOX_FIFO_DATA_MASK +#define MBOX_FIFO_DATA_GET(x) WLAN_MBOX_FIFO_DATA_GET(x) +#define MBOX_FIFO_DATA_SET(x) WLAN_MBOX_FIFO_DATA_SET(x) +#define MBOX_FIFO_STATUS_ADDRESS WLAN_MBOX_FIFO_STATUS_ADDRESS +#define MBOX_FIFO_STATUS_OFFSET WLAN_MBOX_FIFO_STATUS_OFFSET +#define MBOX_FIFO_STATUS_EMPTY_MSB WLAN_MBOX_FIFO_STATUS_EMPTY_MSB +#define MBOX_FIFO_STATUS_EMPTY_LSB WLAN_MBOX_FIFO_STATUS_EMPTY_LSB +#define MBOX_FIFO_STATUS_EMPTY_MASK WLAN_MBOX_FIFO_STATUS_EMPTY_MASK +#define MBOX_FIFO_STATUS_EMPTY_GET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x) +#define MBOX_FIFO_STATUS_EMPTY_SET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x) +#define MBOX_FIFO_STATUS_FULL_MSB WLAN_MBOX_FIFO_STATUS_FULL_MSB +#define MBOX_FIFO_STATUS_FULL_LSB WLAN_MBOX_FIFO_STATUS_FULL_LSB +#define MBOX_FIFO_STATUS_FULL_MASK WLAN_MBOX_FIFO_STATUS_FULL_MASK +#define MBOX_FIFO_STATUS_FULL_GET(x) WLAN_MBOX_FIFO_STATUS_FULL_GET(x) +#define MBOX_FIFO_STATUS_FULL_SET(x) WLAN_MBOX_FIFO_STATUS_FULL_SET(x) +#define MBOX_DMA_POLICY_ADDRESS WLAN_MBOX_DMA_POLICY_ADDRESS +#define MBOX_DMA_POLICY_OFFSET WLAN_MBOX_DMA_POLICY_OFFSET +#define MBOX_DMA_POLICY_TX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB +#define MBOX_DMA_POLICY_TX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB +#define MBOX_DMA_POLICY_TX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK +#define MBOX_DMA_POLICY_TX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x) +#define MBOX_DMA_POLICY_TX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x) +#define MBOX_DMA_POLICY_TX_ORDER_MSB WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB +#define MBOX_DMA_POLICY_TX_ORDER_LSB WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB +#define MBOX_DMA_POLICY_TX_ORDER_MASK WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK +#define MBOX_DMA_POLICY_TX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x) +#define MBOX_DMA_POLICY_TX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x) +#define MBOX_DMA_POLICY_RX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB +#define MBOX_DMA_POLICY_RX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB +#define MBOX_DMA_POLICY_RX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK +#define MBOX_DMA_POLICY_RX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x) +#define MBOX_DMA_POLICY_RX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x) +#define MBOX_DMA_POLICY_RX_ORDER_MSB WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB +#define MBOX_DMA_POLICY_RX_ORDER_LSB WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB +#define MBOX_DMA_POLICY_RX_ORDER_MASK WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK +#define MBOX_DMA_POLICY_RX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x) +#define MBOX_DMA_POLICY_RX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x) +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX0_DMA_RX_CONTROL_ADDRESS WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS +#define MBOX0_DMA_RX_CONTROL_OFFSET WLAN_MBOX0_DMA_RX_CONTROL_OFFSET +#define MBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB +#define MBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB +#define MBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK +#define MBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX0_DMA_RX_CONTROL_START_MSB WLAN_MBOX0_DMA_RX_CONTROL_START_MSB +#define MBOX0_DMA_RX_CONTROL_START_LSB WLAN_MBOX0_DMA_RX_CONTROL_START_LSB +#define MBOX0_DMA_RX_CONTROL_START_MASK WLAN_MBOX0_DMA_RX_CONTROL_START_MASK +#define MBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x) +#define MBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x) +#define MBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB +#define MBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB +#define MBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK +#define MBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX0_DMA_TX_CONTROL_ADDRESS WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS +#define MBOX0_DMA_TX_CONTROL_OFFSET WLAN_MBOX0_DMA_TX_CONTROL_OFFSET +#define MBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB +#define MBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB +#define MBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK +#define MBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX0_DMA_TX_CONTROL_START_MSB WLAN_MBOX0_DMA_TX_CONTROL_START_MSB +#define MBOX0_DMA_TX_CONTROL_START_LSB WLAN_MBOX0_DMA_TX_CONTROL_START_LSB +#define MBOX0_DMA_TX_CONTROL_START_MASK WLAN_MBOX0_DMA_TX_CONTROL_START_MASK +#define MBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x) +#define MBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x) +#define MBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB +#define MBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB +#define MBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK +#define MBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX1_DMA_RX_CONTROL_ADDRESS WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS +#define MBOX1_DMA_RX_CONTROL_OFFSET WLAN_MBOX1_DMA_RX_CONTROL_OFFSET +#define MBOX1_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB +#define MBOX1_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB +#define MBOX1_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK +#define MBOX1_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX1_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX1_DMA_RX_CONTROL_START_MSB WLAN_MBOX1_DMA_RX_CONTROL_START_MSB +#define MBOX1_DMA_RX_CONTROL_START_LSB WLAN_MBOX1_DMA_RX_CONTROL_START_LSB +#define MBOX1_DMA_RX_CONTROL_START_MASK WLAN_MBOX1_DMA_RX_CONTROL_START_MASK +#define MBOX1_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x) +#define MBOX1_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x) +#define MBOX1_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB +#define MBOX1_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB +#define MBOX1_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK +#define MBOX1_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX1_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX1_DMA_TX_CONTROL_ADDRESS WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS +#define MBOX1_DMA_TX_CONTROL_OFFSET WLAN_MBOX1_DMA_TX_CONTROL_OFFSET +#define MBOX1_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB +#define MBOX1_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB +#define MBOX1_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK +#define MBOX1_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX1_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX1_DMA_TX_CONTROL_START_MSB WLAN_MBOX1_DMA_TX_CONTROL_START_MSB +#define MBOX1_DMA_TX_CONTROL_START_LSB WLAN_MBOX1_DMA_TX_CONTROL_START_LSB +#define MBOX1_DMA_TX_CONTROL_START_MASK WLAN_MBOX1_DMA_TX_CONTROL_START_MASK +#define MBOX1_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x) +#define MBOX1_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x) +#define MBOX1_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB +#define MBOX1_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB +#define MBOX1_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK +#define MBOX1_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX1_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX2_DMA_RX_CONTROL_ADDRESS WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS +#define MBOX2_DMA_RX_CONTROL_OFFSET WLAN_MBOX2_DMA_RX_CONTROL_OFFSET +#define MBOX2_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB +#define MBOX2_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB +#define MBOX2_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK +#define MBOX2_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX2_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX2_DMA_RX_CONTROL_START_MSB WLAN_MBOX2_DMA_RX_CONTROL_START_MSB +#define MBOX2_DMA_RX_CONTROL_START_LSB WLAN_MBOX2_DMA_RX_CONTROL_START_LSB +#define MBOX2_DMA_RX_CONTROL_START_MASK WLAN_MBOX2_DMA_RX_CONTROL_START_MASK +#define MBOX2_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x) +#define MBOX2_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x) +#define MBOX2_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB +#define MBOX2_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB +#define MBOX2_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK +#define MBOX2_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX2_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX2_DMA_TX_CONTROL_ADDRESS WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS +#define MBOX2_DMA_TX_CONTROL_OFFSET WLAN_MBOX2_DMA_TX_CONTROL_OFFSET +#define MBOX2_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB +#define MBOX2_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB +#define MBOX2_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK +#define MBOX2_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX2_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX2_DMA_TX_CONTROL_START_MSB WLAN_MBOX2_DMA_TX_CONTROL_START_MSB +#define MBOX2_DMA_TX_CONTROL_START_LSB WLAN_MBOX2_DMA_TX_CONTROL_START_LSB +#define MBOX2_DMA_TX_CONTROL_START_MASK WLAN_MBOX2_DMA_TX_CONTROL_START_MASK +#define MBOX2_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x) +#define MBOX2_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x) +#define MBOX2_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB +#define MBOX2_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB +#define MBOX2_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK +#define MBOX2_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX2_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX3_DMA_RX_CONTROL_ADDRESS WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS +#define MBOX3_DMA_RX_CONTROL_OFFSET WLAN_MBOX3_DMA_RX_CONTROL_OFFSET +#define MBOX3_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB +#define MBOX3_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB +#define MBOX3_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK +#define MBOX3_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX3_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX3_DMA_RX_CONTROL_START_MSB WLAN_MBOX3_DMA_RX_CONTROL_START_MSB +#define MBOX3_DMA_RX_CONTROL_START_LSB WLAN_MBOX3_DMA_RX_CONTROL_START_LSB +#define MBOX3_DMA_RX_CONTROL_START_MASK WLAN_MBOX3_DMA_RX_CONTROL_START_MASK +#define MBOX3_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x) +#define MBOX3_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x) +#define MBOX3_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB +#define MBOX3_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB +#define MBOX3_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK +#define MBOX3_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX3_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX3_DMA_TX_CONTROL_ADDRESS WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS +#define MBOX3_DMA_TX_CONTROL_OFFSET WLAN_MBOX3_DMA_TX_CONTROL_OFFSET +#define MBOX3_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB +#define MBOX3_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB +#define MBOX3_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK +#define MBOX3_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX3_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX3_DMA_TX_CONTROL_START_MSB WLAN_MBOX3_DMA_TX_CONTROL_START_MSB +#define MBOX3_DMA_TX_CONTROL_START_LSB WLAN_MBOX3_DMA_TX_CONTROL_START_LSB +#define MBOX3_DMA_TX_CONTROL_START_MASK WLAN_MBOX3_DMA_TX_CONTROL_START_MASK +#define MBOX3_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x) +#define MBOX3_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x) +#define MBOX3_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB +#define MBOX3_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB +#define MBOX3_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK +#define MBOX3_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX3_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX_INT_STATUS_ADDRESS WLAN_MBOX_INT_STATUS_ADDRESS +#define MBOX_INT_STATUS_OFFSET WLAN_MBOX_INT_STATUS_OFFSET +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB +#define MBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB +#define MBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK +#define MBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x) +#define MBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x) +#define MBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB +#define MBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB +#define MBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK +#define MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) +#define MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) +#define MBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB +#define MBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB +#define MBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK +#define MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) +#define MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) +#define MBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB +#define MBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB +#define MBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK +#define MBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x) +#define MBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x) +#define MBOX_INT_STATUS_HOST_MSB WLAN_MBOX_INT_STATUS_HOST_MSB +#define MBOX_INT_STATUS_HOST_LSB WLAN_MBOX_INT_STATUS_HOST_LSB +#define MBOX_INT_STATUS_HOST_MASK WLAN_MBOX_INT_STATUS_HOST_MASK +#define MBOX_INT_STATUS_HOST_GET(x) WLAN_MBOX_INT_STATUS_HOST_GET(x) +#define MBOX_INT_STATUS_HOST_SET(x) WLAN_MBOX_INT_STATUS_HOST_SET(x) +#define MBOX_INT_ENABLE_ADDRESS WLAN_MBOX_INT_ENABLE_ADDRESS +#define MBOX_INT_ENABLE_OFFSET WLAN_MBOX_INT_ENABLE_OFFSET +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB +#define MBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB +#define MBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK +#define MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) +#define MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) +#define MBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB +#define MBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB +#define MBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK +#define MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) +#define MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) +#define MBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB +#define MBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB +#define MBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK +#define MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) +#define MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) +#define MBOX_INT_ENABLE_HOST_MSB WLAN_MBOX_INT_ENABLE_HOST_MSB +#define MBOX_INT_ENABLE_HOST_LSB WLAN_MBOX_INT_ENABLE_HOST_LSB +#define MBOX_INT_ENABLE_HOST_MASK WLAN_MBOX_INT_ENABLE_HOST_MASK +#define MBOX_INT_ENABLE_HOST_GET(x) WLAN_MBOX_INT_ENABLE_HOST_GET(x) +#define MBOX_INT_ENABLE_HOST_SET(x) WLAN_MBOX_INT_ENABLE_HOST_SET(x) +#define INT_HOST_ADDRESS WLAN_INT_HOST_ADDRESS +#define INT_HOST_OFFSET WLAN_INT_HOST_OFFSET +#define INT_HOST_VECTOR_MSB WLAN_INT_HOST_VECTOR_MSB +#define INT_HOST_VECTOR_LSB WLAN_INT_HOST_VECTOR_LSB +#define INT_HOST_VECTOR_MASK WLAN_INT_HOST_VECTOR_MASK +#define INT_HOST_VECTOR_GET(x) WLAN_INT_HOST_VECTOR_GET(x) +#define INT_HOST_VECTOR_SET(x) WLAN_INT_HOST_VECTOR_SET(x) +#define LOCAL_COUNT_ADDRESS WLAN_LOCAL_COUNT_ADDRESS +#define LOCAL_COUNT_OFFSET WLAN_LOCAL_COUNT_OFFSET +#define LOCAL_COUNT_VALUE_MSB WLAN_LOCAL_COUNT_VALUE_MSB +#define LOCAL_COUNT_VALUE_LSB WLAN_LOCAL_COUNT_VALUE_LSB +#define LOCAL_COUNT_VALUE_MASK WLAN_LOCAL_COUNT_VALUE_MASK +#define LOCAL_COUNT_VALUE_GET(x) WLAN_LOCAL_COUNT_VALUE_GET(x) +#define LOCAL_COUNT_VALUE_SET(x) WLAN_LOCAL_COUNT_VALUE_SET(x) +#define COUNT_INC_ADDRESS WLAN_COUNT_INC_ADDRESS +#define COUNT_INC_OFFSET WLAN_COUNT_INC_OFFSET +#define COUNT_INC_VALUE_MSB WLAN_COUNT_INC_VALUE_MSB +#define COUNT_INC_VALUE_LSB WLAN_COUNT_INC_VALUE_LSB +#define COUNT_INC_VALUE_MASK WLAN_COUNT_INC_VALUE_MASK +#define COUNT_INC_VALUE_GET(x) WLAN_COUNT_INC_VALUE_GET(x) +#define COUNT_INC_VALUE_SET(x) WLAN_COUNT_INC_VALUE_SET(x) +#define LOCAL_SCRATCH_ADDRESS WLAN_LOCAL_SCRATCH_ADDRESS +#define LOCAL_SCRATCH_OFFSET WLAN_LOCAL_SCRATCH_OFFSET +#define LOCAL_SCRATCH_VALUE_MSB WLAN_LOCAL_SCRATCH_VALUE_MSB +#define LOCAL_SCRATCH_VALUE_LSB WLAN_LOCAL_SCRATCH_VALUE_LSB +#define LOCAL_SCRATCH_VALUE_MASK WLAN_LOCAL_SCRATCH_VALUE_MASK +#define LOCAL_SCRATCH_VALUE_GET(x) WLAN_LOCAL_SCRATCH_VALUE_GET(x) +#define LOCAL_SCRATCH_VALUE_SET(x) WLAN_LOCAL_SCRATCH_VALUE_SET(x) +#define USE_LOCAL_BUS_ADDRESS WLAN_USE_LOCAL_BUS_ADDRESS +#define USE_LOCAL_BUS_OFFSET WLAN_USE_LOCAL_BUS_OFFSET +#define USE_LOCAL_BUS_PIN_INIT_MSB WLAN_USE_LOCAL_BUS_PIN_INIT_MSB +#define USE_LOCAL_BUS_PIN_INIT_LSB WLAN_USE_LOCAL_BUS_PIN_INIT_LSB +#define USE_LOCAL_BUS_PIN_INIT_MASK WLAN_USE_LOCAL_BUS_PIN_INIT_MASK +#define USE_LOCAL_BUS_PIN_INIT_GET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x) +#define USE_LOCAL_BUS_PIN_INIT_SET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x) +#define SDIO_CONFIG_ADDRESS WLAN_SDIO_CONFIG_ADDRESS +#define SDIO_CONFIG_OFFSET WLAN_SDIO_CONFIG_OFFSET +#define SDIO_CONFIG_CCCR_IOR1_MSB WLAN_SDIO_CONFIG_CCCR_IOR1_MSB +#define SDIO_CONFIG_CCCR_IOR1_LSB WLAN_SDIO_CONFIG_CCCR_IOR1_LSB +#define SDIO_CONFIG_CCCR_IOR1_MASK WLAN_SDIO_CONFIG_CCCR_IOR1_MASK +#define SDIO_CONFIG_CCCR_IOR1_GET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x) +#define SDIO_CONFIG_CCCR_IOR1_SET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x) +#define MBOX_DEBUG_ADDRESS WLAN_MBOX_DEBUG_ADDRESS +#define MBOX_DEBUG_OFFSET WLAN_MBOX_DEBUG_OFFSET +#define MBOX_DEBUG_SEL_MSB WLAN_MBOX_DEBUG_SEL_MSB +#define MBOX_DEBUG_SEL_LSB WLAN_MBOX_DEBUG_SEL_LSB +#define MBOX_DEBUG_SEL_MASK WLAN_MBOX_DEBUG_SEL_MASK +#define MBOX_DEBUG_SEL_GET(x) WLAN_MBOX_DEBUG_SEL_GET(x) +#define MBOX_DEBUG_SEL_SET(x) WLAN_MBOX_DEBUG_SEL_SET(x) +#define MBOX_FIFO_RESET_ADDRESS WLAN_MBOX_FIFO_RESET_ADDRESS +#define MBOX_FIFO_RESET_OFFSET WLAN_MBOX_FIFO_RESET_OFFSET +#define MBOX_FIFO_RESET_INIT_MSB WLAN_MBOX_FIFO_RESET_INIT_MSB +#define MBOX_FIFO_RESET_INIT_LSB WLAN_MBOX_FIFO_RESET_INIT_LSB +#define MBOX_FIFO_RESET_INIT_MASK WLAN_MBOX_FIFO_RESET_INIT_MASK +#define MBOX_FIFO_RESET_INIT_GET(x) WLAN_MBOX_FIFO_RESET_INIT_GET(x) +#define MBOX_FIFO_RESET_INIT_SET(x) WLAN_MBOX_FIFO_RESET_INIT_SET(x) +#define MBOX_TXFIFO_POP_ADDRESS WLAN_MBOX_TXFIFO_POP_ADDRESS +#define MBOX_TXFIFO_POP_OFFSET WLAN_MBOX_TXFIFO_POP_OFFSET +#define MBOX_TXFIFO_POP_DATA_MSB WLAN_MBOX_TXFIFO_POP_DATA_MSB +#define MBOX_TXFIFO_POP_DATA_LSB WLAN_MBOX_TXFIFO_POP_DATA_LSB +#define MBOX_TXFIFO_POP_DATA_MASK WLAN_MBOX_TXFIFO_POP_DATA_MASK +#define MBOX_TXFIFO_POP_DATA_GET(x) WLAN_MBOX_TXFIFO_POP_DATA_GET(x) +#define MBOX_TXFIFO_POP_DATA_SET(x) WLAN_MBOX_TXFIFO_POP_DATA_SET(x) +#define MBOX_RXFIFO_POP_ADDRESS WLAN_MBOX_RXFIFO_POP_ADDRESS +#define MBOX_RXFIFO_POP_OFFSET WLAN_MBOX_RXFIFO_POP_OFFSET +#define MBOX_RXFIFO_POP_DATA_MSB WLAN_MBOX_RXFIFO_POP_DATA_MSB +#define MBOX_RXFIFO_POP_DATA_LSB WLAN_MBOX_RXFIFO_POP_DATA_LSB +#define MBOX_RXFIFO_POP_DATA_MASK WLAN_MBOX_RXFIFO_POP_DATA_MASK +#define MBOX_RXFIFO_POP_DATA_GET(x) WLAN_MBOX_RXFIFO_POP_DATA_GET(x) +#define MBOX_RXFIFO_POP_DATA_SET(x) WLAN_MBOX_RXFIFO_POP_DATA_SET(x) +#define SDIO_DEBUG_ADDRESS WLAN_SDIO_DEBUG_ADDRESS +#define SDIO_DEBUG_OFFSET WLAN_SDIO_DEBUG_OFFSET +#define SDIO_DEBUG_SEL_MSB WLAN_SDIO_DEBUG_SEL_MSB +#define SDIO_DEBUG_SEL_LSB WLAN_SDIO_DEBUG_SEL_LSB +#define SDIO_DEBUG_SEL_MASK WLAN_SDIO_DEBUG_SEL_MASK +#define SDIO_DEBUG_SEL_GET(x) WLAN_SDIO_DEBUG_SEL_GET(x) +#define SDIO_DEBUG_SEL_SET(x) WLAN_SDIO_DEBUG_SEL_SET(x) +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define GMBOX0_DMA_RX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS +#define GMBOX0_DMA_RX_CONTROL_OFFSET WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET +#define GMBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB +#define GMBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB +#define GMBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK +#define GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) +#define GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) +#define GMBOX0_DMA_RX_CONTROL_START_MSB WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB +#define GMBOX0_DMA_RX_CONTROL_START_LSB WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB +#define GMBOX0_DMA_RX_CONTROL_START_MASK WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK +#define GMBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x) +#define GMBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x) +#define GMBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB +#define GMBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB +#define GMBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK +#define GMBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x) +#define GMBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x) +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define GMBOX0_DMA_TX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS +#define GMBOX0_DMA_TX_CONTROL_OFFSET WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET +#define GMBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB +#define GMBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB +#define GMBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK +#define GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) +#define GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) +#define GMBOX0_DMA_TX_CONTROL_START_MSB WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB +#define GMBOX0_DMA_TX_CONTROL_START_LSB WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB +#define GMBOX0_DMA_TX_CONTROL_START_MASK WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK +#define GMBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x) +#define GMBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x) +#define GMBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB +#define GMBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB +#define GMBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK +#define GMBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x) +#define GMBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x) +#define GMBOX_INT_STATUS_ADDRESS WLAN_GMBOX_INT_STATUS_ADDRESS +#define GMBOX_INT_STATUS_OFFSET WLAN_GMBOX_INT_STATUS_OFFSET +#define GMBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB +#define GMBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB +#define GMBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK +#define GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) +#define GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) +#define GMBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB +#define GMBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB +#define GMBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK +#define GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) +#define GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) +#define GMBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB +#define GMBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB +#define GMBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK +#define GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) +#define GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) +#define GMBOX_INT_ENABLE_ADDRESS WLAN_GMBOX_INT_ENABLE_ADDRESS +#define GMBOX_INT_ENABLE_OFFSET WLAN_GMBOX_INT_ENABLE_OFFSET +#define GMBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB +#define GMBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB +#define GMBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK +#define GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) +#define GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) +#define GMBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB +#define GMBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB +#define GMBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK +#define GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) +#define GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) +#define HOST_IF_WINDOW_ADDRESS WLAN_HOST_IF_WINDOW_ADDRESS +#define HOST_IF_WINDOW_OFFSET WLAN_HOST_IF_WINDOW_OFFSET +#define HOST_IF_WINDOW_DATA_MSB WLAN_HOST_IF_WINDOW_DATA_MSB +#define HOST_IF_WINDOW_DATA_LSB WLAN_HOST_IF_WINDOW_DATA_LSB +#define HOST_IF_WINDOW_DATA_MASK WLAN_HOST_IF_WINDOW_DATA_MASK +#define HOST_IF_WINDOW_DATA_GET(x) WLAN_HOST_IF_WINDOW_DATA_GET(x) +#define HOST_IF_WINDOW_DATA_SET(x) WLAN_HOST_IF_WINDOW_DATA_SET(x) + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h new file mode 100644 index 000000000000..038d0d019273 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h @@ -0,0 +1,471 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _MBOX_WLAN_HOST_REG_REG_H_ +#define _MBOX_WLAN_HOST_REG_REG_H_ + +#define HOST_INT_STATUS_ADDRESS 0x00000400 +#define HOST_INT_STATUS_OFFSET 0x00000400 +#define HOST_INT_STATUS_ERROR_MSB 7 +#define HOST_INT_STATUS_ERROR_LSB 7 +#define HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_ERROR_SET(x) (((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_CPU_MSB 6 +#define HOST_INT_STATUS_CPU_LSB 6 +#define HOST_INT_STATUS_CPU_MASK 0x00000040 +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_CPU_SET(x) (((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_INT_MSB 5 +#define HOST_INT_STATUS_INT_LSB 5 +#define HOST_INT_STATUS_INT_MASK 0x00000020 +#define HOST_INT_STATUS_INT_GET(x) (((x) & HOST_INT_STATUS_INT_MASK) >> HOST_INT_STATUS_INT_LSB) +#define HOST_INT_STATUS_INT_SET(x) (((x) << HOST_INT_STATUS_INT_LSB) & HOST_INT_STATUS_INT_MASK) +#define HOST_INT_STATUS_COUNTER_MSB 4 +#define HOST_INT_STATUS_COUNTER_LSB 4 +#define HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define HOST_INT_STATUS_COUNTER_SET(x) (((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_MBOX_DATA_MSB 3 +#define HOST_INT_STATUS_MBOX_DATA_LSB 0 +#define HOST_INT_STATUS_MBOX_DATA_MASK 0x0000000f +#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB) +#define HOST_INT_STATUS_MBOX_DATA_SET(x) (((x) << HOST_INT_STATUS_MBOX_DATA_LSB) & HOST_INT_STATUS_MBOX_DATA_MASK) + +#define CPU_INT_STATUS_ADDRESS 0x00000401 +#define CPU_INT_STATUS_OFFSET 0x00000401 +#define CPU_INT_STATUS_BIT_MSB 7 +#define CPU_INT_STATUS_BIT_LSB 0 +#define CPU_INT_STATUS_BIT_MASK 0x000000ff +#define CPU_INT_STATUS_BIT_GET(x) (((x) & CPU_INT_STATUS_BIT_MASK) >> CPU_INT_STATUS_BIT_LSB) +#define CPU_INT_STATUS_BIT_SET(x) (((x) << CPU_INT_STATUS_BIT_LSB) & CPU_INT_STATUS_BIT_MASK) + +#define ERROR_INT_STATUS_ADDRESS 0x00000402 +#define ERROR_INT_STATUS_OFFSET 0x00000402 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MSB 6 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB 6 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MSB 5 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB 5 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MSB 4 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB 4 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_SPI_MSB 3 +#define ERROR_INT_STATUS_SPI_LSB 3 +#define ERROR_INT_STATUS_SPI_MASK 0x00000008 +#define ERROR_INT_STATUS_SPI_GET(x) (((x) & ERROR_INT_STATUS_SPI_MASK) >> ERROR_INT_STATUS_SPI_LSB) +#define ERROR_INT_STATUS_SPI_SET(x) (((x) << ERROR_INT_STATUS_SPI_LSB) & ERROR_INT_STATUS_SPI_MASK) +#define ERROR_INT_STATUS_WAKEUP_MSB 2 +#define ERROR_INT_STATUS_WAKEUP_LSB 2 +#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004 +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_WAKEUP_SET(x) (((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1 +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1 +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002 +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0 +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0 +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001 +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) + +#define COUNTER_INT_STATUS_ADDRESS 0x00000403 +#define COUNTER_INT_STATUS_OFFSET 0x00000403 +#define COUNTER_INT_STATUS_COUNTER_MSB 7 +#define COUNTER_INT_STATUS_COUNTER_LSB 0 +#define COUNTER_INT_STATUS_COUNTER_MASK 0x000000ff +#define COUNTER_INT_STATUS_COUNTER_GET(x) (((x) & COUNTER_INT_STATUS_COUNTER_MASK) >> COUNTER_INT_STATUS_COUNTER_LSB) +#define COUNTER_INT_STATUS_COUNTER_SET(x) (((x) << COUNTER_INT_STATUS_COUNTER_LSB) & COUNTER_INT_STATUS_COUNTER_MASK) + +#define MBOX_FRAME_ADDRESS 0x00000404 +#define MBOX_FRAME_OFFSET 0x00000404 +#define MBOX_FRAME_RX_EOM_MSB 7 +#define MBOX_FRAME_RX_EOM_LSB 4 +#define MBOX_FRAME_RX_EOM_MASK 0x000000f0 +#define MBOX_FRAME_RX_EOM_GET(x) (((x) & MBOX_FRAME_RX_EOM_MASK) >> MBOX_FRAME_RX_EOM_LSB) +#define MBOX_FRAME_RX_EOM_SET(x) (((x) << MBOX_FRAME_RX_EOM_LSB) & MBOX_FRAME_RX_EOM_MASK) +#define MBOX_FRAME_RX_SOM_MSB 3 +#define MBOX_FRAME_RX_SOM_LSB 0 +#define MBOX_FRAME_RX_SOM_MASK 0x0000000f +#define MBOX_FRAME_RX_SOM_GET(x) (((x) & MBOX_FRAME_RX_SOM_MASK) >> MBOX_FRAME_RX_SOM_LSB) +#define MBOX_FRAME_RX_SOM_SET(x) (((x) << MBOX_FRAME_RX_SOM_LSB) & MBOX_FRAME_RX_SOM_MASK) + +#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405 +#define RX_LOOKAHEAD_VALID_OFFSET 0x00000405 +#define RX_LOOKAHEAD_VALID_MBOX_MSB 3 +#define RX_LOOKAHEAD_VALID_MBOX_LSB 0 +#define RX_LOOKAHEAD_VALID_MBOX_MASK 0x0000000f +#define RX_LOOKAHEAD_VALID_MBOX_GET(x) (((x) & RX_LOOKAHEAD_VALID_MBOX_MASK) >> RX_LOOKAHEAD_VALID_MBOX_LSB) +#define RX_LOOKAHEAD_VALID_MBOX_SET(x) (((x) << RX_LOOKAHEAD_VALID_MBOX_LSB) & RX_LOOKAHEAD_VALID_MBOX_MASK) + +#define HOST_INT_STATUS2_ADDRESS 0x00000406 +#define HOST_INT_STATUS2_OFFSET 0x00000406 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MSB 2 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB 2 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK 0x00000004 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB) +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK) +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MSB 1 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB 1 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK 0x00000002 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK) +#define HOST_INT_STATUS2_GMBOX_DATA_MSB 0 +#define HOST_INT_STATUS2_GMBOX_DATA_LSB 0 +#define HOST_INT_STATUS2_GMBOX_DATA_MASK 0x00000001 +#define HOST_INT_STATUS2_GMBOX_DATA_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_DATA_MASK) >> HOST_INT_STATUS2_GMBOX_DATA_LSB) +#define HOST_INT_STATUS2_GMBOX_DATA_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_DATA_LSB) & HOST_INT_STATUS2_GMBOX_DATA_MASK) + +#define GMBOX_RX_AVAIL_ADDRESS 0x00000407 +#define GMBOX_RX_AVAIL_OFFSET 0x00000407 +#define GMBOX_RX_AVAIL_BYTE_MSB 6 +#define GMBOX_RX_AVAIL_BYTE_LSB 0 +#define GMBOX_RX_AVAIL_BYTE_MASK 0x0000007f +#define GMBOX_RX_AVAIL_BYTE_GET(x) (((x) & GMBOX_RX_AVAIL_BYTE_MASK) >> GMBOX_RX_AVAIL_BYTE_LSB) +#define GMBOX_RX_AVAIL_BYTE_SET(x) (((x) << GMBOX_RX_AVAIL_BYTE_LSB) & GMBOX_RX_AVAIL_BYTE_MASK) + +#define RX_LOOKAHEAD0_ADDRESS 0x00000408 +#define RX_LOOKAHEAD0_OFFSET 0x00000408 +#define RX_LOOKAHEAD0_DATA_MSB 7 +#define RX_LOOKAHEAD0_DATA_LSB 0 +#define RX_LOOKAHEAD0_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD0_DATA_GET(x) (((x) & RX_LOOKAHEAD0_DATA_MASK) >> RX_LOOKAHEAD0_DATA_LSB) +#define RX_LOOKAHEAD0_DATA_SET(x) (((x) << RX_LOOKAHEAD0_DATA_LSB) & RX_LOOKAHEAD0_DATA_MASK) + +#define RX_LOOKAHEAD1_ADDRESS 0x0000040c +#define RX_LOOKAHEAD1_OFFSET 0x0000040c +#define RX_LOOKAHEAD1_DATA_MSB 7 +#define RX_LOOKAHEAD1_DATA_LSB 0 +#define RX_LOOKAHEAD1_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD1_DATA_GET(x) (((x) & RX_LOOKAHEAD1_DATA_MASK) >> RX_LOOKAHEAD1_DATA_LSB) +#define RX_LOOKAHEAD1_DATA_SET(x) (((x) << RX_LOOKAHEAD1_DATA_LSB) & RX_LOOKAHEAD1_DATA_MASK) + +#define RX_LOOKAHEAD2_ADDRESS 0x00000410 +#define RX_LOOKAHEAD2_OFFSET 0x00000410 +#define RX_LOOKAHEAD2_DATA_MSB 7 +#define RX_LOOKAHEAD2_DATA_LSB 0 +#define RX_LOOKAHEAD2_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD2_DATA_GET(x) (((x) & RX_LOOKAHEAD2_DATA_MASK) >> RX_LOOKAHEAD2_DATA_LSB) +#define RX_LOOKAHEAD2_DATA_SET(x) (((x) << RX_LOOKAHEAD2_DATA_LSB) & RX_LOOKAHEAD2_DATA_MASK) + +#define RX_LOOKAHEAD3_ADDRESS 0x00000414 +#define RX_LOOKAHEAD3_OFFSET 0x00000414 +#define RX_LOOKAHEAD3_DATA_MSB 7 +#define RX_LOOKAHEAD3_DATA_LSB 0 +#define RX_LOOKAHEAD3_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD3_DATA_GET(x) (((x) & RX_LOOKAHEAD3_DATA_MASK) >> RX_LOOKAHEAD3_DATA_LSB) +#define RX_LOOKAHEAD3_DATA_SET(x) (((x) << RX_LOOKAHEAD3_DATA_LSB) & RX_LOOKAHEAD3_DATA_MASK) + +#define INT_STATUS_ENABLE_ADDRESS 0x00000418 +#define INT_STATUS_ENABLE_OFFSET 0x00000418 +#define INT_STATUS_ENABLE_ERROR_MSB 7 +#define INT_STATUS_ENABLE_ERROR_LSB 7 +#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define INT_STATUS_ENABLE_ERROR_GET(x) (((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_MSB 6 +#define INT_STATUS_ENABLE_CPU_LSB 6 +#define INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define INT_STATUS_ENABLE_CPU_GET(x) (((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_INT_MSB 5 +#define INT_STATUS_ENABLE_INT_LSB 5 +#define INT_STATUS_ENABLE_INT_MASK 0x00000020 +#define INT_STATUS_ENABLE_INT_GET(x) (((x) & INT_STATUS_ENABLE_INT_MASK) >> INT_STATUS_ENABLE_INT_LSB) +#define INT_STATUS_ENABLE_INT_SET(x) (((x) << INT_STATUS_ENABLE_INT_LSB) & INT_STATUS_ENABLE_INT_MASK) +#define INT_STATUS_ENABLE_COUNTER_MSB 4 +#define INT_STATUS_ENABLE_COUNTER_LSB 4 +#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define INT_STATUS_ENABLE_COUNTER_GET(x) (((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3 +#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) (((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) + +#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419 +#define CPU_INT_STATUS_ENABLE_OFFSET 0x00000419 +#define CPU_INT_STATUS_ENABLE_BIT_MSB 7 +#define CPU_INT_STATUS_ENABLE_BIT_LSB 0 +#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff +#define CPU_INT_STATUS_ENABLE_BIT_GET(x) (((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) + +#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a +#define ERROR_STATUS_ENABLE_OFFSET 0x0000041a +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MSB 6 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB 6 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MSB 5 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB 5 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MSB 4 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB 4 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_WAKEUP_MSB 2 +#define ERROR_STATUS_ENABLE_WAKEUP_LSB 2 +#define ERROR_STATUS_ENABLE_WAKEUP_MASK 0x00000004 +#define ERROR_STATUS_ENABLE_WAKEUP_GET(x) (((x) & ERROR_STATUS_ENABLE_WAKEUP_MASK) >> ERROR_STATUS_ENABLE_WAKEUP_LSB) +#define ERROR_STATUS_ENABLE_WAKEUP_SET(x) (((x) << ERROR_STATUS_ENABLE_WAKEUP_LSB) & ERROR_STATUS_ENABLE_WAKEUP_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) + +#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b +#define COUNTER_INT_STATUS_ENABLE_OFFSET 0x0000041b +#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7 +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0 +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff +#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) (((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) + +#define COUNT_ADDRESS 0x00000420 +#define COUNT_OFFSET 0x00000420 +#define COUNT_VALUE_MSB 7 +#define COUNT_VALUE_LSB 0 +#define COUNT_VALUE_MASK 0x000000ff +#define COUNT_VALUE_GET(x) (((x) & COUNT_VALUE_MASK) >> COUNT_VALUE_LSB) +#define COUNT_VALUE_SET(x) (((x) << COUNT_VALUE_LSB) & COUNT_VALUE_MASK) + +#define COUNT_DEC_ADDRESS 0x00000440 +#define COUNT_DEC_OFFSET 0x00000440 +#define COUNT_DEC_VALUE_MSB 7 +#define COUNT_DEC_VALUE_LSB 0 +#define COUNT_DEC_VALUE_MASK 0x000000ff +#define COUNT_DEC_VALUE_GET(x) (((x) & COUNT_DEC_VALUE_MASK) >> COUNT_DEC_VALUE_LSB) +#define COUNT_DEC_VALUE_SET(x) (((x) << COUNT_DEC_VALUE_LSB) & COUNT_DEC_VALUE_MASK) + +#define SCRATCH_ADDRESS 0x00000460 +#define SCRATCH_OFFSET 0x00000460 +#define SCRATCH_VALUE_MSB 7 +#define SCRATCH_VALUE_LSB 0 +#define SCRATCH_VALUE_MASK 0x000000ff +#define SCRATCH_VALUE_GET(x) (((x) & SCRATCH_VALUE_MASK) >> SCRATCH_VALUE_LSB) +#define SCRATCH_VALUE_SET(x) (((x) << SCRATCH_VALUE_LSB) & SCRATCH_VALUE_MASK) + +#define FIFO_TIMEOUT_ADDRESS 0x00000468 +#define FIFO_TIMEOUT_OFFSET 0x00000468 +#define FIFO_TIMEOUT_VALUE_MSB 7 +#define FIFO_TIMEOUT_VALUE_LSB 0 +#define FIFO_TIMEOUT_VALUE_MASK 0x000000ff +#define FIFO_TIMEOUT_VALUE_GET(x) (((x) & FIFO_TIMEOUT_VALUE_MASK) >> FIFO_TIMEOUT_VALUE_LSB) +#define FIFO_TIMEOUT_VALUE_SET(x) (((x) << FIFO_TIMEOUT_VALUE_LSB) & FIFO_TIMEOUT_VALUE_MASK) + +#define FIFO_TIMEOUT_ENABLE_ADDRESS 0x00000469 +#define FIFO_TIMEOUT_ENABLE_OFFSET 0x00000469 +#define FIFO_TIMEOUT_ENABLE_SET_MSB 0 +#define FIFO_TIMEOUT_ENABLE_SET_LSB 0 +#define FIFO_TIMEOUT_ENABLE_SET_MASK 0x00000001 +#define FIFO_TIMEOUT_ENABLE_SET_GET(x) (((x) & FIFO_TIMEOUT_ENABLE_SET_MASK) >> FIFO_TIMEOUT_ENABLE_SET_LSB) +#define FIFO_TIMEOUT_ENABLE_SET_SET(x) (((x) << FIFO_TIMEOUT_ENABLE_SET_LSB) & FIFO_TIMEOUT_ENABLE_SET_MASK) + +#define DISABLE_SLEEP_ADDRESS 0x0000046a +#define DISABLE_SLEEP_OFFSET 0x0000046a +#define DISABLE_SLEEP_FOR_INT_MSB 1 +#define DISABLE_SLEEP_FOR_INT_LSB 1 +#define DISABLE_SLEEP_FOR_INT_MASK 0x00000002 +#define DISABLE_SLEEP_FOR_INT_GET(x) (((x) & DISABLE_SLEEP_FOR_INT_MASK) >> DISABLE_SLEEP_FOR_INT_LSB) +#define DISABLE_SLEEP_FOR_INT_SET(x) (((x) << DISABLE_SLEEP_FOR_INT_LSB) & DISABLE_SLEEP_FOR_INT_MASK) +#define DISABLE_SLEEP_ON_MSB 0 +#define DISABLE_SLEEP_ON_LSB 0 +#define DISABLE_SLEEP_ON_MASK 0x00000001 +#define DISABLE_SLEEP_ON_GET(x) (((x) & DISABLE_SLEEP_ON_MASK) >> DISABLE_SLEEP_ON_LSB) +#define DISABLE_SLEEP_ON_SET(x) (((x) << DISABLE_SLEEP_ON_LSB) & DISABLE_SLEEP_ON_MASK) + +#define LOCAL_BUS_ADDRESS 0x00000470 +#define LOCAL_BUS_OFFSET 0x00000470 +#define LOCAL_BUS_STATE_MSB 1 +#define LOCAL_BUS_STATE_LSB 0 +#define LOCAL_BUS_STATE_MASK 0x00000003 +#define LOCAL_BUS_STATE_GET(x) (((x) & LOCAL_BUS_STATE_MASK) >> LOCAL_BUS_STATE_LSB) +#define LOCAL_BUS_STATE_SET(x) (((x) << LOCAL_BUS_STATE_LSB) & LOCAL_BUS_STATE_MASK) + +#define INT_WLAN_ADDRESS 0x00000472 +#define INT_WLAN_OFFSET 0x00000472 +#define INT_WLAN_VECTOR_MSB 7 +#define INT_WLAN_VECTOR_LSB 0 +#define INT_WLAN_VECTOR_MASK 0x000000ff +#define INT_WLAN_VECTOR_GET(x) (((x) & INT_WLAN_VECTOR_MASK) >> INT_WLAN_VECTOR_LSB) +#define INT_WLAN_VECTOR_SET(x) (((x) << INT_WLAN_VECTOR_LSB) & INT_WLAN_VECTOR_MASK) + +#define WINDOW_DATA_ADDRESS 0x00000474 +#define WINDOW_DATA_OFFSET 0x00000474 +#define WINDOW_DATA_DATA_MSB 7 +#define WINDOW_DATA_DATA_LSB 0 +#define WINDOW_DATA_DATA_MASK 0x000000ff +#define WINDOW_DATA_DATA_GET(x) (((x) & WINDOW_DATA_DATA_MASK) >> WINDOW_DATA_DATA_LSB) +#define WINDOW_DATA_DATA_SET(x) (((x) << WINDOW_DATA_DATA_LSB) & WINDOW_DATA_DATA_MASK) + +#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478 +#define WINDOW_WRITE_ADDR_OFFSET 0x00000478 +#define WINDOW_WRITE_ADDR_ADDR_MSB 7 +#define WINDOW_WRITE_ADDR_ADDR_LSB 0 +#define WINDOW_WRITE_ADDR_ADDR_MASK 0x000000ff +#define WINDOW_WRITE_ADDR_ADDR_GET(x) (((x) & WINDOW_WRITE_ADDR_ADDR_MASK) >> WINDOW_WRITE_ADDR_ADDR_LSB) +#define WINDOW_WRITE_ADDR_ADDR_SET(x) (((x) << WINDOW_WRITE_ADDR_ADDR_LSB) & WINDOW_WRITE_ADDR_ADDR_MASK) + +#define WINDOW_READ_ADDR_ADDRESS 0x0000047c +#define WINDOW_READ_ADDR_OFFSET 0x0000047c +#define WINDOW_READ_ADDR_ADDR_MSB 7 +#define WINDOW_READ_ADDR_ADDR_LSB 0 +#define WINDOW_READ_ADDR_ADDR_MASK 0x000000ff +#define WINDOW_READ_ADDR_ADDR_GET(x) (((x) & WINDOW_READ_ADDR_ADDR_MASK) >> WINDOW_READ_ADDR_ADDR_LSB) +#define WINDOW_READ_ADDR_ADDR_SET(x) (((x) << WINDOW_READ_ADDR_ADDR_LSB) & WINDOW_READ_ADDR_ADDR_MASK) + +#define HOST_CTRL_SPI_CONFIG_ADDRESS 0x00000480 +#define HOST_CTRL_SPI_CONFIG_OFFSET 0x00000480 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MSB 4 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB 4 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK 0x00000010 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK) >> HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB) +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK) +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MSB 3 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB 3 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK 0x00000008 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK) >> HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB) +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK) +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MSB 2 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB 2 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK 0x00000004 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK) >> HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB) +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK) +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MSB 1 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB 0 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK 0x00000003 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK) >> HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB) +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK) + +#define HOST_CTRL_SPI_STATUS_ADDRESS 0x00000481 +#define HOST_CTRL_SPI_STATUS_OFFSET 0x00000481 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MSB 3 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB 3 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK 0x00000008 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_RD_ERR_MSB 2 +#define HOST_CTRL_SPI_STATUS_RD_ERR_LSB 2 +#define HOST_CTRL_SPI_STATUS_RD_ERR_MASK 0x00000004 +#define HOST_CTRL_SPI_STATUS_RD_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK) >> HOST_CTRL_SPI_STATUS_RD_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_RD_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_RD_ERR_LSB) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_WR_ERR_MSB 1 +#define HOST_CTRL_SPI_STATUS_WR_ERR_LSB 1 +#define HOST_CTRL_SPI_STATUS_WR_ERR_MASK 0x00000002 +#define HOST_CTRL_SPI_STATUS_WR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_WR_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_WR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_WR_ERR_LSB) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_READY_MSB 0 +#define HOST_CTRL_SPI_STATUS_READY_LSB 0 +#define HOST_CTRL_SPI_STATUS_READY_MASK 0x00000001 +#define HOST_CTRL_SPI_STATUS_READY_GET(x) (((x) & HOST_CTRL_SPI_STATUS_READY_MASK) >> HOST_CTRL_SPI_STATUS_READY_LSB) +#define HOST_CTRL_SPI_STATUS_READY_SET(x) (((x) << HOST_CTRL_SPI_STATUS_READY_LSB) & HOST_CTRL_SPI_STATUS_READY_MASK) + +#define NON_ASSOC_SLEEP_EN_ADDRESS 0x00000482 +#define NON_ASSOC_SLEEP_EN_OFFSET 0x00000482 +#define NON_ASSOC_SLEEP_EN_BIT_MSB 0 +#define NON_ASSOC_SLEEP_EN_BIT_LSB 0 +#define NON_ASSOC_SLEEP_EN_BIT_MASK 0x00000001 +#define NON_ASSOC_SLEEP_EN_BIT_GET(x) (((x) & NON_ASSOC_SLEEP_EN_BIT_MASK) >> NON_ASSOC_SLEEP_EN_BIT_LSB) +#define NON_ASSOC_SLEEP_EN_BIT_SET(x) (((x) << NON_ASSOC_SLEEP_EN_BIT_LSB) & NON_ASSOC_SLEEP_EN_BIT_MASK) + +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_SEL_OFFSET 0x00000483 +#define CPU_DBG_SEL_BIT_MSB 5 +#define CPU_DBG_SEL_BIT_LSB 0 +#define CPU_DBG_SEL_BIT_MASK 0x0000003f +#define CPU_DBG_SEL_BIT_GET(x) (((x) & CPU_DBG_SEL_BIT_MASK) >> CPU_DBG_SEL_BIT_LSB) +#define CPU_DBG_SEL_BIT_SET(x) (((x) << CPU_DBG_SEL_BIT_LSB) & CPU_DBG_SEL_BIT_MASK) + +#define CPU_DBG_ADDRESS 0x00000484 +#define CPU_DBG_OFFSET 0x00000484 +#define CPU_DBG_DATA_MSB 7 +#define CPU_DBG_DATA_LSB 0 +#define CPU_DBG_DATA_MASK 0x000000ff +#define CPU_DBG_DATA_GET(x) (((x) & CPU_DBG_DATA_MASK) >> CPU_DBG_DATA_LSB) +#define CPU_DBG_DATA_SET(x) (((x) << CPU_DBG_DATA_LSB) & CPU_DBG_DATA_MASK) + +#define INT_STATUS2_ENABLE_ADDRESS 0x00000488 +#define INT_STATUS2_ENABLE_OFFSET 0x00000488 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MSB 2 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB 2 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK 0x00000004 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB) +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK) +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MSB 1 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB 1 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK 0x00000002 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB) +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK) +#define INT_STATUS2_ENABLE_GMBOX_DATA_MSB 0 +#define INT_STATUS2_ENABLE_GMBOX_DATA_LSB 0 +#define INT_STATUS2_ENABLE_GMBOX_DATA_MASK 0x00000001 +#define INT_STATUS2_ENABLE_GMBOX_DATA_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK) >> INT_STATUS2_ENABLE_GMBOX_DATA_LSB) +#define INT_STATUS2_ENABLE_GMBOX_DATA_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_DATA_LSB) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK) + +#define GMBOX_RX_LOOKAHEAD_ADDRESS 0x00000490 +#define GMBOX_RX_LOOKAHEAD_OFFSET 0x00000490 +#define GMBOX_RX_LOOKAHEAD_DATA_MSB 7 +#define GMBOX_RX_LOOKAHEAD_DATA_LSB 0 +#define GMBOX_RX_LOOKAHEAD_DATA_MASK 0x000000ff +#define GMBOX_RX_LOOKAHEAD_DATA_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_DATA_MASK) >> GMBOX_RX_LOOKAHEAD_DATA_LSB) +#define GMBOX_RX_LOOKAHEAD_DATA_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_DATA_LSB) & GMBOX_RX_LOOKAHEAD_DATA_MASK) + +#define GMBOX_RX_LOOKAHEAD_MUX_ADDRESS 0x00000498 +#define GMBOX_RX_LOOKAHEAD_MUX_OFFSET 0x00000498 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MSB 0 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB 0 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK 0x00000001 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK) >> GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB) +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK) + +#define CIS_WINDOW_ADDRESS 0x00000600 +#define CIS_WINDOW_OFFSET 0x00000600 +#define CIS_WINDOW_DATA_MSB 7 +#define CIS_WINDOW_DATA_LSB 0 +#define CIS_WINDOW_DATA_MASK 0x000000ff +#define CIS_WINDOW_DATA_GET(x) (((x) & CIS_WINDOW_DATA_MASK) >> CIS_WINDOW_DATA_LSB) +#define CIS_WINDOW_DATA_SET(x) (((x) << CIS_WINDOW_DATA_LSB) & CIS_WINDOW_DATA_MASK) + + +#endif /* _MBOX_WLAN_HOST_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h new file mode 100644 index 000000000000..f5167b9ae8d0 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h @@ -0,0 +1,589 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _MBOX_WLAN_REG_REG_H_ +#define _MBOX_WLAN_REG_REG_H_ + +#define WLAN_MBOX_FIFO_ADDRESS 0x00000000 +#define WLAN_MBOX_FIFO_OFFSET 0x00000000 +#define WLAN_MBOX_FIFO_DATA_MSB 19 +#define WLAN_MBOX_FIFO_DATA_LSB 0 +#define WLAN_MBOX_FIFO_DATA_MASK 0x000fffff +#define WLAN_MBOX_FIFO_DATA_GET(x) (((x) & WLAN_MBOX_FIFO_DATA_MASK) >> WLAN_MBOX_FIFO_DATA_LSB) +#define WLAN_MBOX_FIFO_DATA_SET(x) (((x) << WLAN_MBOX_FIFO_DATA_LSB) & WLAN_MBOX_FIFO_DATA_MASK) + +#define WLAN_MBOX_FIFO_STATUS_ADDRESS 0x00000010 +#define WLAN_MBOX_FIFO_STATUS_OFFSET 0x00000010 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_MSB 19 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_LSB 16 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_MASK 0x000f0000 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK) >> WLAN_MBOX_FIFO_STATUS_EMPTY_LSB) +#define WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_EMPTY_LSB) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK) +#define WLAN_MBOX_FIFO_STATUS_FULL_MSB 15 +#define WLAN_MBOX_FIFO_STATUS_FULL_LSB 12 +#define WLAN_MBOX_FIFO_STATUS_FULL_MASK 0x0000f000 +#define WLAN_MBOX_FIFO_STATUS_FULL_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_FULL_MASK) >> WLAN_MBOX_FIFO_STATUS_FULL_LSB) +#define WLAN_MBOX_FIFO_STATUS_FULL_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_FULL_LSB) & WLAN_MBOX_FIFO_STATUS_FULL_MASK) + +#define WLAN_MBOX_DMA_POLICY_ADDRESS 0x00000014 +#define WLAN_MBOX_DMA_POLICY_OFFSET 0x00000014 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB 3 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB 3 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK 0x00000008 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB) +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK) +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB 2 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB 2 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK 0x00000004 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB) +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK) +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB 1 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB 1 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK 0x00000002 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB) +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK) +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB 0 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB 0 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK 0x00000001 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB) +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK) + +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000018 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000018 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS 0x0000001c +#define WLAN_MBOX0_DMA_RX_CONTROL_OFFSET 0x0000001c +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX0_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000020 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000020 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS 0x00000024 +#define WLAN_MBOX0_DMA_TX_CONTROL_OFFSET 0x00000024 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX0_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000028 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000028 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS 0x0000002c +#define WLAN_MBOX1_DMA_RX_CONTROL_OFFSET 0x0000002c +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX1_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000030 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000030 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS 0x00000034 +#define WLAN_MBOX1_DMA_TX_CONTROL_OFFSET 0x00000034 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX1_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000038 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000038 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS 0x0000003c +#define WLAN_MBOX2_DMA_RX_CONTROL_OFFSET 0x0000003c +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX2_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000040 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000040 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS 0x00000044 +#define WLAN_MBOX2_DMA_TX_CONTROL_OFFSET 0x00000044 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX2_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000048 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000048 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS 0x0000004c +#define WLAN_MBOX3_DMA_RX_CONTROL_OFFSET 0x0000004c +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX3_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000050 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000050 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS 0x00000054 +#define WLAN_MBOX3_DMA_TX_CONTROL_OFFSET 0x00000054 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX3_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX_INT_STATUS_ADDRESS 0x00000058 +#define WLAN_MBOX_INT_STATUS_OFFSET 0x00000058 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 31 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 28 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0xf0000000 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 27 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 24 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x0f000000 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 23 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 20 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00f00000 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB 17 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB 17 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00020000 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB) +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK) +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB 16 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB 16 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00010000 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB) +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK) +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB 15 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB 12 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x0000f000 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB) +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK) +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB 11 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB 8 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000f00 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB) +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK) +#define WLAN_MBOX_INT_STATUS_HOST_MSB 7 +#define WLAN_MBOX_INT_STATUS_HOST_LSB 0 +#define WLAN_MBOX_INT_STATUS_HOST_MASK 0x000000ff +#define WLAN_MBOX_INT_STATUS_HOST_GET(x) (((x) & WLAN_MBOX_INT_STATUS_HOST_MASK) >> WLAN_MBOX_INT_STATUS_HOST_LSB) +#define WLAN_MBOX_INT_STATUS_HOST_SET(x) (((x) << WLAN_MBOX_INT_STATUS_HOST_LSB) & WLAN_MBOX_INT_STATUS_HOST_MASK) + +#define WLAN_MBOX_INT_ENABLE_ADDRESS 0x0000005c +#define WLAN_MBOX_INT_ENABLE_OFFSET 0x0000005c +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 31 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 28 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0xf0000000 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 27 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 24 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x0f000000 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 23 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 20 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00f00000 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB 17 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB 17 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00020000 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK) +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB 16 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB 16 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00010000 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 15 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 12 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x0000f000 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB 11 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB 8 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000f00 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK) +#define WLAN_MBOX_INT_ENABLE_HOST_MSB 7 +#define WLAN_MBOX_INT_ENABLE_HOST_LSB 0 +#define WLAN_MBOX_INT_ENABLE_HOST_MASK 0x000000ff +#define WLAN_MBOX_INT_ENABLE_HOST_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_HOST_MASK) >> WLAN_MBOX_INT_ENABLE_HOST_LSB) +#define WLAN_MBOX_INT_ENABLE_HOST_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_HOST_LSB) & WLAN_MBOX_INT_ENABLE_HOST_MASK) + +#define WLAN_INT_HOST_ADDRESS 0x00000060 +#define WLAN_INT_HOST_OFFSET 0x00000060 +#define WLAN_INT_HOST_VECTOR_MSB 7 +#define WLAN_INT_HOST_VECTOR_LSB 0 +#define WLAN_INT_HOST_VECTOR_MASK 0x000000ff +#define WLAN_INT_HOST_VECTOR_GET(x) (((x) & WLAN_INT_HOST_VECTOR_MASK) >> WLAN_INT_HOST_VECTOR_LSB) +#define WLAN_INT_HOST_VECTOR_SET(x) (((x) << WLAN_INT_HOST_VECTOR_LSB) & WLAN_INT_HOST_VECTOR_MASK) + +#define WLAN_LOCAL_COUNT_ADDRESS 0x00000080 +#define WLAN_LOCAL_COUNT_OFFSET 0x00000080 +#define WLAN_LOCAL_COUNT_VALUE_MSB 7 +#define WLAN_LOCAL_COUNT_VALUE_LSB 0 +#define WLAN_LOCAL_COUNT_VALUE_MASK 0x000000ff +#define WLAN_LOCAL_COUNT_VALUE_GET(x) (((x) & WLAN_LOCAL_COUNT_VALUE_MASK) >> WLAN_LOCAL_COUNT_VALUE_LSB) +#define WLAN_LOCAL_COUNT_VALUE_SET(x) (((x) << WLAN_LOCAL_COUNT_VALUE_LSB) & WLAN_LOCAL_COUNT_VALUE_MASK) + +#define WLAN_COUNT_INC_ADDRESS 0x000000a0 +#define WLAN_COUNT_INC_OFFSET 0x000000a0 +#define WLAN_COUNT_INC_VALUE_MSB 7 +#define WLAN_COUNT_INC_VALUE_LSB 0 +#define WLAN_COUNT_INC_VALUE_MASK 0x000000ff +#define WLAN_COUNT_INC_VALUE_GET(x) (((x) & WLAN_COUNT_INC_VALUE_MASK) >> WLAN_COUNT_INC_VALUE_LSB) +#define WLAN_COUNT_INC_VALUE_SET(x) (((x) << WLAN_COUNT_INC_VALUE_LSB) & WLAN_COUNT_INC_VALUE_MASK) + +#define WLAN_LOCAL_SCRATCH_ADDRESS 0x000000c0 +#define WLAN_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define WLAN_LOCAL_SCRATCH_VALUE_MSB 7 +#define WLAN_LOCAL_SCRATCH_VALUE_LSB 0 +#define WLAN_LOCAL_SCRATCH_VALUE_MASK 0x000000ff +#define WLAN_LOCAL_SCRATCH_VALUE_GET(x) (((x) & WLAN_LOCAL_SCRATCH_VALUE_MASK) >> WLAN_LOCAL_SCRATCH_VALUE_LSB) +#define WLAN_LOCAL_SCRATCH_VALUE_SET(x) (((x) << WLAN_LOCAL_SCRATCH_VALUE_LSB) & WLAN_LOCAL_SCRATCH_VALUE_MASK) + +#define WLAN_USE_LOCAL_BUS_ADDRESS 0x000000e0 +#define WLAN_USE_LOCAL_BUS_OFFSET 0x000000e0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_MSB 0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_LSB 0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_MASK 0x00000001 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x) (((x) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK) >> WLAN_USE_LOCAL_BUS_PIN_INIT_LSB) +#define WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x) (((x) << WLAN_USE_LOCAL_BUS_PIN_INIT_LSB) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK) + +#define WLAN_SDIO_CONFIG_ADDRESS 0x000000e4 +#define WLAN_SDIO_CONFIG_OFFSET 0x000000e4 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_MSB 0 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_LSB 0 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_MASK 0x00000001 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x) (((x) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK) >> WLAN_SDIO_CONFIG_CCCR_IOR1_LSB) +#define WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x) (((x) << WLAN_SDIO_CONFIG_CCCR_IOR1_LSB) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK) + +#define WLAN_MBOX_DEBUG_ADDRESS 0x000000e8 +#define WLAN_MBOX_DEBUG_OFFSET 0x000000e8 +#define WLAN_MBOX_DEBUG_SEL_MSB 2 +#define WLAN_MBOX_DEBUG_SEL_LSB 0 +#define WLAN_MBOX_DEBUG_SEL_MASK 0x00000007 +#define WLAN_MBOX_DEBUG_SEL_GET(x) (((x) & WLAN_MBOX_DEBUG_SEL_MASK) >> WLAN_MBOX_DEBUG_SEL_LSB) +#define WLAN_MBOX_DEBUG_SEL_SET(x) (((x) << WLAN_MBOX_DEBUG_SEL_LSB) & WLAN_MBOX_DEBUG_SEL_MASK) + +#define WLAN_MBOX_FIFO_RESET_ADDRESS 0x000000ec +#define WLAN_MBOX_FIFO_RESET_OFFSET 0x000000ec +#define WLAN_MBOX_FIFO_RESET_INIT_MSB 0 +#define WLAN_MBOX_FIFO_RESET_INIT_LSB 0 +#define WLAN_MBOX_FIFO_RESET_INIT_MASK 0x00000001 +#define WLAN_MBOX_FIFO_RESET_INIT_GET(x) (((x) & WLAN_MBOX_FIFO_RESET_INIT_MASK) >> WLAN_MBOX_FIFO_RESET_INIT_LSB) +#define WLAN_MBOX_FIFO_RESET_INIT_SET(x) (((x) << WLAN_MBOX_FIFO_RESET_INIT_LSB) & WLAN_MBOX_FIFO_RESET_INIT_MASK) + +#define WLAN_MBOX_TXFIFO_POP_ADDRESS 0x000000f0 +#define WLAN_MBOX_TXFIFO_POP_OFFSET 0x000000f0 +#define WLAN_MBOX_TXFIFO_POP_DATA_MSB 0 +#define WLAN_MBOX_TXFIFO_POP_DATA_LSB 0 +#define WLAN_MBOX_TXFIFO_POP_DATA_MASK 0x00000001 +#define WLAN_MBOX_TXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_TXFIFO_POP_DATA_MASK) >> WLAN_MBOX_TXFIFO_POP_DATA_LSB) +#define WLAN_MBOX_TXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_TXFIFO_POP_DATA_LSB) & WLAN_MBOX_TXFIFO_POP_DATA_MASK) + +#define WLAN_MBOX_RXFIFO_POP_ADDRESS 0x00000100 +#define WLAN_MBOX_RXFIFO_POP_OFFSET 0x00000100 +#define WLAN_MBOX_RXFIFO_POP_DATA_MSB 0 +#define WLAN_MBOX_RXFIFO_POP_DATA_LSB 0 +#define WLAN_MBOX_RXFIFO_POP_DATA_MASK 0x00000001 +#define WLAN_MBOX_RXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_RXFIFO_POP_DATA_MASK) >> WLAN_MBOX_RXFIFO_POP_DATA_LSB) +#define WLAN_MBOX_RXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_RXFIFO_POP_DATA_LSB) & WLAN_MBOX_RXFIFO_POP_DATA_MASK) + +#define WLAN_SDIO_DEBUG_ADDRESS 0x00000110 +#define WLAN_SDIO_DEBUG_OFFSET 0x00000110 +#define WLAN_SDIO_DEBUG_SEL_MSB 3 +#define WLAN_SDIO_DEBUG_SEL_LSB 0 +#define WLAN_SDIO_DEBUG_SEL_MASK 0x0000000f +#define WLAN_SDIO_DEBUG_SEL_GET(x) (((x) & WLAN_SDIO_DEBUG_SEL_MASK) >> WLAN_SDIO_DEBUG_SEL_LSB) +#define WLAN_SDIO_DEBUG_SEL_SET(x) (((x) << WLAN_SDIO_DEBUG_SEL_LSB) & WLAN_SDIO_DEBUG_SEL_MASK) + +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000114 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000114 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS 0x00000118 +#define WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET 0x00000118 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK) +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x0000011c +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x0000011c +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS 0x00000120 +#define WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET 0x00000120 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK) +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_GMBOX_INT_STATUS_ADDRESS 0x00000124 +#define WLAN_GMBOX_INT_STATUS_OFFSET 0x00000124 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB 6 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB 6 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00000040 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB 5 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB 5 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00000020 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 4 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 4 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0x00000010 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 3 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 3 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x00000008 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 2 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 2 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00000004 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB 1 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB 1 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x00000002 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB 0 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB 0 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000001 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK) + +#define WLAN_GMBOX_INT_ENABLE_ADDRESS 0x00000128 +#define WLAN_GMBOX_INT_ENABLE_OFFSET 0x00000128 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB 6 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB 6 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00000040 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB 5 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB 5 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00000020 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 4 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 4 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0x00000010 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 3 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 3 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x00000008 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 2 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 2 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00000004 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 1 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 1 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x00000002 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB 0 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB 0 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000001 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK) + +#define WLAN_HOST_IF_WINDOW_ADDRESS 0x00002000 +#define WLAN_HOST_IF_WINDOW_OFFSET 0x00002000 +#define WLAN_HOST_IF_WINDOW_DATA_MSB 7 +#define WLAN_HOST_IF_WINDOW_DATA_LSB 0 +#define WLAN_HOST_IF_WINDOW_DATA_MASK 0x000000ff +#define WLAN_HOST_IF_WINDOW_DATA_GET(x) (((x) & WLAN_HOST_IF_WINDOW_DATA_MASK) >> WLAN_HOST_IF_WINDOW_DATA_LSB) +#define WLAN_HOST_IF_WINDOW_DATA_SET(x) (((x) << WLAN_HOST_IF_WINDOW_DATA_LSB) & WLAN_HOST_IF_WINDOW_DATA_MASK) + +#endif /* _MBOX_WLAN_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h new file mode 100644 index 000000000000..fcafec88a6b9 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h @@ -0,0 +1,187 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "rtc_wlan_reg.h" + +#ifndef BT_HEADERS + +#define RESET_CONTROL_ADDRESS WLAN_RESET_CONTROL_ADDRESS +#define RESET_CONTROL_OFFSET WLAN_RESET_CONTROL_OFFSET +#define RESET_CONTROL_DEBUG_UART_RST_MSB WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB +#define RESET_CONTROL_DEBUG_UART_RST_LSB WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB +#define RESET_CONTROL_DEBUG_UART_RST_MASK WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK +#define RESET_CONTROL_DEBUG_UART_RST_GET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x) +#define RESET_CONTROL_DEBUG_UART_RST_SET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x) +#define RESET_CONTROL_BB_COLD_RST_MSB WLAN_RESET_CONTROL_BB_COLD_RST_MSB +#define RESET_CONTROL_BB_COLD_RST_LSB WLAN_RESET_CONTROL_BB_COLD_RST_LSB +#define RESET_CONTROL_BB_COLD_RST_MASK WLAN_RESET_CONTROL_BB_COLD_RST_MASK +#define RESET_CONTROL_BB_COLD_RST_GET(x) WLAN_RESET_CONTROL_BB_COLD_RST_GET(x) +#define RESET_CONTROL_BB_COLD_RST_SET(x) WLAN_RESET_CONTROL_BB_COLD_RST_SET(x) +#define RESET_CONTROL_BB_WARM_RST_MSB WLAN_RESET_CONTROL_BB_WARM_RST_MSB +#define RESET_CONTROL_BB_WARM_RST_LSB WLAN_RESET_CONTROL_BB_WARM_RST_LSB +#define RESET_CONTROL_BB_WARM_RST_MASK WLAN_RESET_CONTROL_BB_WARM_RST_MASK +#define RESET_CONTROL_BB_WARM_RST_GET(x) WLAN_RESET_CONTROL_BB_WARM_RST_GET(x) +#define RESET_CONTROL_BB_WARM_RST_SET(x) WLAN_RESET_CONTROL_BB_WARM_RST_SET(x) +#define RESET_CONTROL_CPU_INIT_RESET_MSB WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB +#define RESET_CONTROL_CPU_INIT_RESET_LSB WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB +#define RESET_CONTROL_CPU_INIT_RESET_MASK WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK +#define RESET_CONTROL_CPU_INIT_RESET_GET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x) +#define RESET_CONTROL_CPU_INIT_RESET_SET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x) +#define RESET_CONTROL_VMC_REMAP_RESET_MSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB +#define RESET_CONTROL_VMC_REMAP_RESET_LSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB +#define RESET_CONTROL_VMC_REMAP_RESET_MASK WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK +#define RESET_CONTROL_VMC_REMAP_RESET_GET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x) +#define RESET_CONTROL_VMC_REMAP_RESET_SET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x) +#define RESET_CONTROL_RST_OUT_MSB WLAN_RESET_CONTROL_RST_OUT_MSB +#define RESET_CONTROL_RST_OUT_LSB WLAN_RESET_CONTROL_RST_OUT_LSB +#define RESET_CONTROL_RST_OUT_MASK WLAN_RESET_CONTROL_RST_OUT_MASK +#define RESET_CONTROL_RST_OUT_GET(x) WLAN_RESET_CONTROL_RST_OUT_GET(x) +#define RESET_CONTROL_RST_OUT_SET(x) WLAN_RESET_CONTROL_RST_OUT_SET(x) +#define RESET_CONTROL_COLD_RST_MSB WLAN_RESET_CONTROL_COLD_RST_MSB +#define RESET_CONTROL_COLD_RST_LSB WLAN_RESET_CONTROL_COLD_RST_LSB +#define RESET_CONTROL_COLD_RST_MASK WLAN_RESET_CONTROL_COLD_RST_MASK +#define RESET_CONTROL_COLD_RST_GET(x) WLAN_RESET_CONTROL_COLD_RST_GET(x) +#define RESET_CONTROL_COLD_RST_SET(x) WLAN_RESET_CONTROL_COLD_RST_SET(x) +#define RESET_CONTROL_WARM_RST_MSB WLAN_RESET_CONTROL_WARM_RST_MSB +#define RESET_CONTROL_WARM_RST_LSB WLAN_RESET_CONTROL_WARM_RST_LSB +#define RESET_CONTROL_WARM_RST_MASK WLAN_RESET_CONTROL_WARM_RST_MASK +#define RESET_CONTROL_WARM_RST_GET(x) WLAN_RESET_CONTROL_WARM_RST_GET(x) +#define RESET_CONTROL_WARM_RST_SET(x) WLAN_RESET_CONTROL_WARM_RST_SET(x) +#define RESET_CONTROL_CPU_WARM_RST_MSB WLAN_RESET_CONTROL_CPU_WARM_RST_MSB +#define RESET_CONTROL_CPU_WARM_RST_LSB WLAN_RESET_CONTROL_CPU_WARM_RST_LSB +#define RESET_CONTROL_CPU_WARM_RST_MASK WLAN_RESET_CONTROL_CPU_WARM_RST_MASK +#define RESET_CONTROL_CPU_WARM_RST_GET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x) +#define RESET_CONTROL_CPU_WARM_RST_SET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x) +#define RESET_CONTROL_MAC_COLD_RST_MSB WLAN_RESET_CONTROL_MAC_COLD_RST_MSB +#define RESET_CONTROL_MAC_COLD_RST_LSB WLAN_RESET_CONTROL_MAC_COLD_RST_LSB +#define RESET_CONTROL_MAC_COLD_RST_MASK WLAN_RESET_CONTROL_MAC_COLD_RST_MASK +#define RESET_CONTROL_MAC_COLD_RST_GET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x) +#define RESET_CONTROL_MAC_COLD_RST_SET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x) +#define RESET_CONTROL_MAC_WARM_RST_MSB WLAN_RESET_CONTROL_MAC_WARM_RST_MSB +#define RESET_CONTROL_MAC_WARM_RST_LSB WLAN_RESET_CONTROL_MAC_WARM_RST_LSB +#define RESET_CONTROL_MAC_WARM_RST_MASK WLAN_RESET_CONTROL_MAC_WARM_RST_MASK +#define RESET_CONTROL_MAC_WARM_RST_GET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x) +#define RESET_CONTROL_MAC_WARM_RST_SET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x) +#define RESET_CONTROL_MBOX_RST_MSB WLAN_RESET_CONTROL_MBOX_RST_MSB +#define RESET_CONTROL_MBOX_RST_LSB WLAN_RESET_CONTROL_MBOX_RST_LSB +#define RESET_CONTROL_MBOX_RST_MASK WLAN_RESET_CONTROL_MBOX_RST_MASK +#define RESET_CONTROL_MBOX_RST_GET(x) WLAN_RESET_CONTROL_MBOX_RST_GET(x) +#define RESET_CONTROL_MBOX_RST_SET(x) WLAN_RESET_CONTROL_MBOX_RST_SET(x) +#define RESET_CONTROL_UART_RST_MSB WLAN_RESET_CONTROL_UART_RST_MSB +#define RESET_CONTROL_UART_RST_LSB WLAN_RESET_CONTROL_UART_RST_LSB +#define RESET_CONTROL_UART_RST_MASK WLAN_RESET_CONTROL_UART_RST_MASK +#define RESET_CONTROL_UART_RST_GET(x) WLAN_RESET_CONTROL_UART_RST_GET(x) +#define RESET_CONTROL_UART_RST_SET(x) WLAN_RESET_CONTROL_UART_RST_SET(x) +#define RESET_CONTROL_SI0_RST_MSB WLAN_RESET_CONTROL_SI0_RST_MSB +#define RESET_CONTROL_SI0_RST_LSB WLAN_RESET_CONTROL_SI0_RST_LSB +#define RESET_CONTROL_SI0_RST_MASK WLAN_RESET_CONTROL_SI0_RST_MASK +#define RESET_CONTROL_SI0_RST_GET(x) WLAN_RESET_CONTROL_SI0_RST_GET(x) +#define RESET_CONTROL_SI0_RST_SET(x) WLAN_RESET_CONTROL_SI0_RST_SET(x) +#define CPU_CLOCK_ADDRESS WLAN_CPU_CLOCK_ADDRESS +#define CPU_CLOCK_OFFSET WLAN_CPU_CLOCK_OFFSET +#define CPU_CLOCK_STANDARD_MSB WLAN_CPU_CLOCK_STANDARD_MSB +#define CPU_CLOCK_STANDARD_LSB WLAN_CPU_CLOCK_STANDARD_LSB +#define CPU_CLOCK_STANDARD_MASK WLAN_CPU_CLOCK_STANDARD_MASK +#define CPU_CLOCK_STANDARD_GET(x) WLAN_CPU_CLOCK_STANDARD_GET(x) +#define CPU_CLOCK_STANDARD_SET(x) WLAN_CPU_CLOCK_STANDARD_SET(x) +#define CLOCK_OUT_ADDRESS WLAN_CLOCK_OUT_ADDRESS +#define CLOCK_OUT_OFFSET WLAN_CLOCK_OUT_OFFSET +#define CLOCK_OUT_SELECT_MSB WLAN_CLOCK_OUT_SELECT_MSB +#define CLOCK_OUT_SELECT_LSB WLAN_CLOCK_OUT_SELECT_LSB +#define CLOCK_OUT_SELECT_MASK WLAN_CLOCK_OUT_SELECT_MASK +#define CLOCK_OUT_SELECT_GET(x) WLAN_CLOCK_OUT_SELECT_GET(x) +#define CLOCK_OUT_SELECT_SET(x) WLAN_CLOCK_OUT_SELECT_SET(x) +#define CLOCK_CONTROL_ADDRESS WLAN_CLOCK_CONTROL_ADDRESS +#define CLOCK_CONTROL_OFFSET WLAN_CLOCK_CONTROL_OFFSET +#define CLOCK_CONTROL_LF_CLK32_MSB WLAN_CLOCK_CONTROL_LF_CLK32_MSB +#define CLOCK_CONTROL_LF_CLK32_LSB WLAN_CLOCK_CONTROL_LF_CLK32_LSB +#define CLOCK_CONTROL_LF_CLK32_MASK WLAN_CLOCK_CONTROL_LF_CLK32_MASK +#define CLOCK_CONTROL_LF_CLK32_GET(x) WLAN_CLOCK_CONTROL_LF_CLK32_GET(x) +#define CLOCK_CONTROL_LF_CLK32_SET(x) WLAN_CLOCK_CONTROL_LF_CLK32_SET(x) +#define CLOCK_CONTROL_SI0_CLK_MSB WLAN_CLOCK_CONTROL_SI0_CLK_MSB +#define CLOCK_CONTROL_SI0_CLK_LSB WLAN_CLOCK_CONTROL_SI0_CLK_LSB +#define CLOCK_CONTROL_SI0_CLK_MASK WLAN_CLOCK_CONTROL_SI0_CLK_MASK +#define CLOCK_CONTROL_SI0_CLK_GET(x) WLAN_CLOCK_CONTROL_SI0_CLK_GET(x) +#define CLOCK_CONTROL_SI0_CLK_SET(x) WLAN_CLOCK_CONTROL_SI0_CLK_SET(x) +#define RESET_CAUSE_ADDRESS WLAN_RESET_CAUSE_ADDRESS +#define RESET_CAUSE_OFFSET WLAN_RESET_CAUSE_OFFSET +#define RESET_CAUSE_LAST_MSB WLAN_RESET_CAUSE_LAST_MSB +#define RESET_CAUSE_LAST_LSB WLAN_RESET_CAUSE_LAST_LSB +#define RESET_CAUSE_LAST_MASK WLAN_RESET_CAUSE_LAST_MASK +#define RESET_CAUSE_LAST_GET(x) WLAN_RESET_CAUSE_LAST_GET(x) +#define RESET_CAUSE_LAST_SET(x) WLAN_RESET_CAUSE_LAST_SET(x) +#define SYSTEM_SLEEP_ADDRESS WLAN_SYSTEM_SLEEP_ADDRESS +#define SYSTEM_SLEEP_OFFSET WLAN_SYSTEM_SLEEP_OFFSET +#define SYSTEM_SLEEP_HOST_IF_MSB WLAN_SYSTEM_SLEEP_HOST_IF_MSB +#define SYSTEM_SLEEP_HOST_IF_LSB WLAN_SYSTEM_SLEEP_HOST_IF_LSB +#define SYSTEM_SLEEP_HOST_IF_MASK WLAN_SYSTEM_SLEEP_HOST_IF_MASK +#define SYSTEM_SLEEP_HOST_IF_GET(x) WLAN_SYSTEM_SLEEP_HOST_IF_GET(x) +#define SYSTEM_SLEEP_HOST_IF_SET(x) WLAN_SYSTEM_SLEEP_HOST_IF_SET(x) +#define SYSTEM_SLEEP_MBOX_MSB WLAN_SYSTEM_SLEEP_MBOX_MSB +#define SYSTEM_SLEEP_MBOX_LSB WLAN_SYSTEM_SLEEP_MBOX_LSB +#define SYSTEM_SLEEP_MBOX_MASK WLAN_SYSTEM_SLEEP_MBOX_MASK +#define SYSTEM_SLEEP_MBOX_GET(x) WLAN_SYSTEM_SLEEP_MBOX_GET(x) +#define SYSTEM_SLEEP_MBOX_SET(x) WLAN_SYSTEM_SLEEP_MBOX_SET(x) +#define SYSTEM_SLEEP_MAC_IF_MSB WLAN_SYSTEM_SLEEP_MAC_IF_MSB +#define SYSTEM_SLEEP_MAC_IF_LSB WLAN_SYSTEM_SLEEP_MAC_IF_LSB +#define SYSTEM_SLEEP_MAC_IF_MASK WLAN_SYSTEM_SLEEP_MAC_IF_MASK +#define SYSTEM_SLEEP_MAC_IF_GET(x) WLAN_SYSTEM_SLEEP_MAC_IF_GET(x) +#define SYSTEM_SLEEP_MAC_IF_SET(x) WLAN_SYSTEM_SLEEP_MAC_IF_SET(x) +#define SYSTEM_SLEEP_LIGHT_MSB WLAN_SYSTEM_SLEEP_LIGHT_MSB +#define SYSTEM_SLEEP_LIGHT_LSB WLAN_SYSTEM_SLEEP_LIGHT_LSB +#define SYSTEM_SLEEP_LIGHT_MASK WLAN_SYSTEM_SLEEP_LIGHT_MASK +#define SYSTEM_SLEEP_LIGHT_GET(x) WLAN_SYSTEM_SLEEP_LIGHT_GET(x) +#define SYSTEM_SLEEP_LIGHT_SET(x) WLAN_SYSTEM_SLEEP_LIGHT_SET(x) +#define SYSTEM_SLEEP_DISABLE_MSB WLAN_SYSTEM_SLEEP_DISABLE_MSB +#define SYSTEM_SLEEP_DISABLE_LSB WLAN_SYSTEM_SLEEP_DISABLE_LSB +#define SYSTEM_SLEEP_DISABLE_MASK WLAN_SYSTEM_SLEEP_DISABLE_MASK +#define SYSTEM_SLEEP_DISABLE_GET(x) WLAN_SYSTEM_SLEEP_DISABLE_GET(x) +#define SYSTEM_SLEEP_DISABLE_SET(x) WLAN_SYSTEM_SLEEP_DISABLE_SET(x) +#define LPO_INIT_DIVIDEND_INT_ADDRESS WLAN_LPO_INIT_DIVIDEND_INT_ADDRESS +#define LPO_INIT_DIVIDEND_INT_OFFSET WLAN_LPO_INIT_DIVIDEND_INT_OFFSET +#define LPO_INIT_DIVIDEND_INT_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MSB +#define LPO_INIT_DIVIDEND_INT_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_LSB +#define LPO_INIT_DIVIDEND_INT_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MASK +#define LPO_INIT_DIVIDEND_INT_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_GET(x) +#define LPO_INIT_DIVIDEND_INT_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_SET(x) +#define LPO_INIT_DIVIDEND_FRACTION_ADDRESS WLAN_LPO_INIT_DIVIDEND_FRACTION_ADDRESS +#define LPO_INIT_DIVIDEND_FRACTION_OFFSET WLAN_LPO_INIT_DIVIDEND_FRACTION_OFFSET +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) +#define LPO_CAL_ADDRESS WLAN_LPO_CAL_ADDRESS +#define LPO_CAL_OFFSET WLAN_LPO_CAL_OFFSET +#define LPO_CAL_ENABLE_MSB WLAN_LPO_CAL_ENABLE_MSB +#define LPO_CAL_ENABLE_LSB WLAN_LPO_CAL_ENABLE_LSB +#define LPO_CAL_ENABLE_MASK WLAN_LPO_CAL_ENABLE_MASK +#define LPO_CAL_ENABLE_GET(x) WLAN_LPO_CAL_ENABLE_GET(x) +#define LPO_CAL_ENABLE_SET(x) WLAN_LPO_CAL_ENABLE_SET(x) +#define LPO_CAL_COUNT_MSB WLAN_LPO_CAL_COUNT_MSB +#define LPO_CAL_COUNT_LSB WLAN_LPO_CAL_COUNT_LSB +#define LPO_CAL_COUNT_MASK WLAN_LPO_CAL_COUNT_MASK +#define LPO_CAL_COUNT_GET(x) WLAN_LPO_CAL_COUNT_GET(x) +#define LPO_CAL_COUNT_SET(x) WLAN_LPO_CAL_COUNT_SET(x) + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h new file mode 100644 index 000000000000..5c048ff51b07 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h @@ -0,0 +1,162 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _RTC_WLAN_REG_REG_H_ +#define _RTC_WLAN_REG_REG_H_ + +#define WLAN_RESET_CONTROL_ADDRESS 0x00000000 +#define WLAN_RESET_CONTROL_OFFSET 0x00000000 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB 14 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB 14 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK 0x00004000 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK) >> WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB) +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK) +#define WLAN_RESET_CONTROL_BB_COLD_RST_MSB 13 +#define WLAN_RESET_CONTROL_BB_COLD_RST_LSB 13 +#define WLAN_RESET_CONTROL_BB_COLD_RST_MASK 0x00002000 +#define WLAN_RESET_CONTROL_BB_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK) >> WLAN_RESET_CONTROL_BB_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_BB_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_COLD_RST_LSB) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_BB_WARM_RST_MSB 12 +#define WLAN_RESET_CONTROL_BB_WARM_RST_LSB 12 +#define WLAN_RESET_CONTROL_BB_WARM_RST_MASK 0x00001000 +#define WLAN_RESET_CONTROL_BB_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK) >> WLAN_RESET_CONTROL_BB_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_BB_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_WARM_RST_LSB) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB 11 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB 11 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK 0x00000800 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK) >> WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB) +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK) +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB 10 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB 10 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK 0x00000400 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK) >> WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB) +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK) +#define WLAN_RESET_CONTROL_RST_OUT_MSB 9 +#define WLAN_RESET_CONTROL_RST_OUT_LSB 9 +#define WLAN_RESET_CONTROL_RST_OUT_MASK 0x00000200 +#define WLAN_RESET_CONTROL_RST_OUT_GET(x) (((x) & WLAN_RESET_CONTROL_RST_OUT_MASK) >> WLAN_RESET_CONTROL_RST_OUT_LSB) +#define WLAN_RESET_CONTROL_RST_OUT_SET(x) (((x) << WLAN_RESET_CONTROL_RST_OUT_LSB) & WLAN_RESET_CONTROL_RST_OUT_MASK) +#define WLAN_RESET_CONTROL_COLD_RST_MSB 8 +#define WLAN_RESET_CONTROL_COLD_RST_LSB 8 +#define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000100 +#define WLAN_RESET_CONTROL_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_COLD_RST_MASK) >> WLAN_RESET_CONTROL_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_COLD_RST_LSB) & WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MSB 7 +#define WLAN_RESET_CONTROL_WARM_RST_LSB 7 +#define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000080 +#define WLAN_RESET_CONTROL_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_WARM_RST_MASK) >> WLAN_RESET_CONTROL_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_WARM_RST_LSB) & WLAN_RESET_CONTROL_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_CPU_WARM_RST_MSB 6 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_LSB 6 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK) >> WLAN_RESET_CONTROL_CPU_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_WARM_RST_LSB) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_MAC_COLD_RST_MSB 5 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_LSB 5 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_MASK 0x00000020 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK) >> WLAN_RESET_CONTROL_MAC_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_COLD_RST_LSB) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_MAC_WARM_RST_MSB 4 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_LSB 4 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_MASK 0x00000010 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK) >> WLAN_RESET_CONTROL_MAC_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_WARM_RST_LSB) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_MBOX_RST_MSB 2 +#define WLAN_RESET_CONTROL_MBOX_RST_LSB 2 +#define WLAN_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define WLAN_RESET_CONTROL_MBOX_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MBOX_RST_MASK) >> WLAN_RESET_CONTROL_MBOX_RST_LSB) +#define WLAN_RESET_CONTROL_MBOX_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MBOX_RST_LSB) & WLAN_RESET_CONTROL_MBOX_RST_MASK) +#define WLAN_RESET_CONTROL_UART_RST_MSB 1 +#define WLAN_RESET_CONTROL_UART_RST_LSB 1 +#define WLAN_RESET_CONTROL_UART_RST_MASK 0x00000002 +#define WLAN_RESET_CONTROL_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_UART_RST_MASK) >> WLAN_RESET_CONTROL_UART_RST_LSB) +#define WLAN_RESET_CONTROL_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_UART_RST_LSB) & WLAN_RESET_CONTROL_UART_RST_MASK) +#define WLAN_RESET_CONTROL_SI0_RST_MSB 0 +#define WLAN_RESET_CONTROL_SI0_RST_LSB 0 +#define WLAN_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define WLAN_RESET_CONTROL_SI0_RST_GET(x) (((x) & WLAN_RESET_CONTROL_SI0_RST_MASK) >> WLAN_RESET_CONTROL_SI0_RST_LSB) +#define WLAN_RESET_CONTROL_SI0_RST_SET(x) (((x) << WLAN_RESET_CONTROL_SI0_RST_LSB) & WLAN_RESET_CONTROL_SI0_RST_MASK) + +#define WLAN_CPU_CLOCK_ADDRESS 0x00000020 +#define WLAN_CPU_CLOCK_OFFSET 0x00000020 +#define WLAN_CPU_CLOCK_STANDARD_MSB 1 +#define WLAN_CPU_CLOCK_STANDARD_LSB 0 +#define WLAN_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define WLAN_CPU_CLOCK_STANDARD_GET(x) (((x) & WLAN_CPU_CLOCK_STANDARD_MASK) >> WLAN_CPU_CLOCK_STANDARD_LSB) +#define WLAN_CPU_CLOCK_STANDARD_SET(x) (((x) << WLAN_CPU_CLOCK_STANDARD_LSB) & WLAN_CPU_CLOCK_STANDARD_MASK) + +#define WLAN_CLOCK_CONTROL_ADDRESS 0x00000028 +#define WLAN_CLOCK_CONTROL_OFFSET 0x00000028 +#define WLAN_CLOCK_CONTROL_LF_CLK32_MSB 2 +#define WLAN_CLOCK_CONTROL_LF_CLK32_LSB 2 +#define WLAN_CLOCK_CONTROL_LF_CLK32_MASK 0x00000004 +#define WLAN_CLOCK_CONTROL_LF_CLK32_GET(x) (((x) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK) >> WLAN_CLOCK_CONTROL_LF_CLK32_LSB) +#define WLAN_CLOCK_CONTROL_LF_CLK32_SET(x) (((x) << WLAN_CLOCK_CONTROL_LF_CLK32_LSB) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK) +#define WLAN_CLOCK_CONTROL_SI0_CLK_MSB 0 +#define WLAN_CLOCK_CONTROL_SI0_CLK_LSB 0 +#define WLAN_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define WLAN_CLOCK_CONTROL_SI0_CLK_GET(x) (((x) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK) >> WLAN_CLOCK_CONTROL_SI0_CLK_LSB) +#define WLAN_CLOCK_CONTROL_SI0_CLK_SET(x) (((x) << WLAN_CLOCK_CONTROL_SI0_CLK_LSB) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK) + +#define WLAN_SYSTEM_SLEEP_ADDRESS 0x000000c4 +#define WLAN_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_MSB 4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_LSB 4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_MASK 0x00000010 +#define WLAN_SYSTEM_SLEEP_HOST_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK) >> WLAN_SYSTEM_SLEEP_HOST_IF_LSB) +#define WLAN_SYSTEM_SLEEP_HOST_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_HOST_IF_LSB) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK) +#define WLAN_SYSTEM_SLEEP_MBOX_MSB 3 +#define WLAN_SYSTEM_SLEEP_MBOX_LSB 3 +#define WLAN_SYSTEM_SLEEP_MBOX_MASK 0x00000008 +#define WLAN_SYSTEM_SLEEP_MBOX_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MBOX_MASK) >> WLAN_SYSTEM_SLEEP_MBOX_LSB) +#define WLAN_SYSTEM_SLEEP_MBOX_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MBOX_LSB) & WLAN_SYSTEM_SLEEP_MBOX_MASK) +#define WLAN_SYSTEM_SLEEP_MAC_IF_MSB 2 +#define WLAN_SYSTEM_SLEEP_MAC_IF_LSB 2 +#define WLAN_SYSTEM_SLEEP_MAC_IF_MASK 0x00000004 +#define WLAN_SYSTEM_SLEEP_MAC_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK) >> WLAN_SYSTEM_SLEEP_MAC_IF_LSB) +#define WLAN_SYSTEM_SLEEP_MAC_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MAC_IF_LSB) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK) +#define WLAN_SYSTEM_SLEEP_LIGHT_MSB 1 +#define WLAN_SYSTEM_SLEEP_LIGHT_LSB 1 +#define WLAN_SYSTEM_SLEEP_LIGHT_MASK 0x00000002 +#define WLAN_SYSTEM_SLEEP_LIGHT_GET(x) (((x) & WLAN_SYSTEM_SLEEP_LIGHT_MASK) >> WLAN_SYSTEM_SLEEP_LIGHT_LSB) +#define WLAN_SYSTEM_SLEEP_LIGHT_SET(x) (((x) << WLAN_SYSTEM_SLEEP_LIGHT_LSB) & WLAN_SYSTEM_SLEEP_LIGHT_MASK) +#define WLAN_SYSTEM_SLEEP_DISABLE_MSB 0 +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define WLAN_SYSTEM_SLEEP_DISABLE_GET(x) (((x) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) >> WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) + +#define WLAN_LPO_CAL_ADDRESS 0x000000e0 +#define WLAN_LPO_CAL_OFFSET 0x000000e0 +#define WLAN_LPO_CAL_ENABLE_MSB 20 +#define WLAN_LPO_CAL_ENABLE_LSB 20 +#define WLAN_LPO_CAL_ENABLE_MASK 0x00100000 +#define WLAN_LPO_CAL_ENABLE_GET(x) (((x) & WLAN_LPO_CAL_ENABLE_MASK) >> WLAN_LPO_CAL_ENABLE_LSB) +#define WLAN_LPO_CAL_ENABLE_SET(x) (((x) << WLAN_LPO_CAL_ENABLE_LSB) & WLAN_LPO_CAL_ENABLE_MASK) +#define WLAN_LPO_CAL_COUNT_MSB 19 +#define WLAN_LPO_CAL_COUNT_LSB 0 +#define WLAN_LPO_CAL_COUNT_MASK 0x000fffff +#define WLAN_LPO_CAL_COUNT_GET(x) (((x) & WLAN_LPO_CAL_COUNT_MASK) >> WLAN_LPO_CAL_COUNT_LSB) +#define WLAN_LPO_CAL_COUNT_SET(x) (((x) << WLAN_LPO_CAL_COUNT_LSB) & WLAN_LPO_CAL_COUNT_MASK) + +#endif /* _RTC_WLAN_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h new file mode 100644 index 000000000000..302b20bc1bad --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _UART_REG_REG_H_ +#define _UART_REG_REG_H_ + +#define UART_CLKDIV_ADDRESS 0x00000008 +#define UART_CLKDIV_OFFSET 0x00000008 +#define UART_CLKDIV_CLK_SCALE_MSB 23 +#define UART_CLKDIV_CLK_SCALE_LSB 16 +#define UART_CLKDIV_CLK_SCALE_MASK 0x00ff0000 +#define UART_CLKDIV_CLK_SCALE_GET(x) (((x) & UART_CLKDIV_CLK_SCALE_MASK) >> UART_CLKDIV_CLK_SCALE_LSB) +#define UART_CLKDIV_CLK_SCALE_SET(x) (((x) << UART_CLKDIV_CLK_SCALE_LSB) & UART_CLKDIV_CLK_SCALE_MASK) +#define UART_CLKDIV_CLK_STEP_MSB 15 +#define UART_CLKDIV_CLK_STEP_LSB 0 +#define UART_CLKDIV_CLK_STEP_MASK 0x0000ffff +#define UART_CLKDIV_CLK_STEP_GET(x) (((x) & UART_CLKDIV_CLK_STEP_MASK) >> UART_CLKDIV_CLK_STEP_LSB) +#define UART_CLKDIV_CLK_STEP_SET(x) (((x) << UART_CLKDIV_CLK_STEP_LSB) & UART_CLKDIV_CLK_STEP_MASK) + +#endif /* _UART_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/athdefs.h b/trunk/drivers/staging/ath6kl/include/common/athdefs.h new file mode 100644 index 000000000000..74922481e065 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/athdefs.h @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef __ATHDEFS_H__ +#define __ATHDEFS_H__ + +/* + * This file contains definitions that may be used across both + * Host and Target software. Nothing here is module-dependent + * or platform-dependent. + */ + +/* + * Generic error codes that can be used by hw, sta, ap, sim, dk + * and any other environments. + * Feel free to add any more non-zero codes that you need. + */ + +#define A_ERROR (-1) /* Generic error return */ +#define A_DEVICE_NOT_FOUND 1 /* not able to find PCI device */ +#define A_NO_MEMORY 2 /* not able to allocate memory, + * not avail#defineable */ +#define A_MEMORY_NOT_AVAIL 3 /* memory region is not free for + * mapping */ +#define A_NO_FREE_DESC 4 /* no free descriptors available */ +#define A_BAD_ADDRESS 5 /* address does not match descriptor */ +#define A_WIN_DRIVER_ERROR 6 /* used in NT_HW version, + * if problem at init */ +#define A_REGS_NOT_MAPPED 7 /* registers not correctly mapped */ +#define A_EPERM 8 /* Not superuser */ +#define A_EACCES 0 /* Access denied */ +#define A_ENOENT 10 /* No such entry, search failed, etc. */ +#define A_EEXIST 11 /* The object already exists + * (can't create) */ +#define A_EFAULT 12 /* Bad address fault */ +#define A_EBUSY 13 /* Object is busy */ +#define A_EINVAL 14 /* Invalid parameter */ +#define A_EMSGSIZE 15 /* Bad message buffer length */ +#define A_ECANCELED 16 /* Operation canceled */ +#define A_ENOTSUP 17 /* Operation not supported */ +#define A_ECOMM 18 /* Communication error on send */ +#define A_EPROTO 19 /* Protocol error */ +#define A_ENODEV 20 /* No such device */ +#define A_EDEVNOTUP 21 /* device is not UP */ +#define A_NO_RESOURCE 22 /* No resources for + * requested operation */ +#define A_HARDWARE 23 /* Hardware failure */ +#define A_PENDING 24 /* Asynchronous routine; will send up + * results later + * (typically in callback) */ +#define A_EBADCHANNEL 25 /* The channel cannot be used */ +#define A_DECRYPT_ERROR 26 /* Decryption error */ +#define A_PHY_ERROR 27 /* RX PHY error */ +#define A_CONSUMED 28 /* Object was consumed */ + +#endif /* __ATHDEFS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h b/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h new file mode 100644 index 000000000000..84e8db569a9f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h @@ -0,0 +1,233 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __BMI_MSG_H__ +#define __BMI_MSG_H__ + +/* + * Bootloader Messaging Interface (BMI) + * + * BMI is a very simple messaging interface used during initialization + * to read memory, write memory, execute code, and to define an + * application entry PC. + * + * It is used to download an application to AR6K, to provide + * patches to code that is already resident on AR6K, and generally + * to examine and modify state. The Host has an opportunity to use + * BMI only once during bootup. Once the Host issues a BMI_DONE + * command, this opportunity ends. + * + * The Host writes BMI requests to mailbox0, and reads BMI responses + * from mailbox0. BMI requests all begin with a command + * (see below for specific commands), and are followed by + * command-specific data. + * + * Flow control: + * The Host can only issue a command once the Target gives it a + * "BMI Command Credit", using AR6K Counter #4. As soon as the + * Target has completed a command, it issues another BMI Command + * Credit (so the Host can issue the next command). + * + * BMI handles all required Target-side cache flushing. + */ + + +/* Maximum data size used for BMI transfers */ +#define BMI_DATASZ_MAX 256 + +/* BMI Commands */ + +#define BMI_NO_COMMAND 0 + +#define BMI_DONE 1 + /* + * Semantics: Host is done using BMI + * Request format: + * u32 command (BMI_DONE) + * Response format: none + */ + +#define BMI_READ_MEMORY 2 + /* + * Semantics: Host reads AR6K memory + * Request format: + * u32 command (BMI_READ_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * Response format: + * u8 data[length] + */ + +#define BMI_WRITE_MEMORY 3 + /* + * Semantics: Host writes AR6K memory + * Request format: + * u32 command (BMI_WRITE_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * u8 data[length] + * Response format: none + */ + +#define BMI_EXECUTE 4 + /* + * Semantics: Causes AR6K to execute code + * Request format: + * u32 command (BMI_EXECUTE) + * u32 address + * u32 parameter + * Response format: + * u32 return value + */ + +#define BMI_SET_APP_START 5 + /* + * Semantics: Set Target application starting address + * Request format: + * u32 command (BMI_SET_APP_START) + * u32 address + * Response format: none + */ + +#define BMI_READ_SOC_REGISTER 6 + /* + * Semantics: Read a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_READ_REGISTER) + * u32 address + * Response format: + * u32 value + */ + +#define BMI_WRITE_SOC_REGISTER 7 + /* + * Semantics: Write a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_WRITE_REGISTER) + * u32 address + * u32 value + * + * Response format: none + */ + +#define BMI_GET_TARGET_ID 8 +#define BMI_GET_TARGET_INFO 8 + /* + * Semantics: Fetch the 4-byte Target information + * Request format: + * u32 command (BMI_GET_TARGET_ID/INFO) + * Response format1 (old firmware): + * u32 TargetVersionID + * Response format2 (newer firmware): + * u32 TARGET_VERSION_SENTINAL + * struct bmi_target_info; + */ + +PREPACK struct bmi_target_info { + u32 target_info_byte_count; /* size of this structure */ + u32 target_ver; /* Target Version ID */ + u32 target_type; /* Target type */ +} POSTPACK; +#define TARGET_VERSION_SENTINAL 0xffffffff +#define TARGET_TYPE_AR6001 1 +#define TARGET_TYPE_AR6002 2 +#define TARGET_TYPE_AR6003 3 + + +#define BMI_ROMPATCH_INSTALL 9 + /* + * Semantics: Install a ROM Patch. + * Request format: + * u32 command (BMI_ROMPATCH_INSTALL) + * u32 Target ROM Address + * u32 Target RAM Address or Value (depending on Target Type) + * u32 Size, in bytes + * u32 Activate? 1-->activate; + * 0-->install but do not activate + * Response format: + * u32 PatchID + */ + +#define BMI_ROMPATCH_UNINSTALL 10 + /* + * Semantics: Uninstall a previously-installed ROM Patch, + * automatically deactivating, if necessary. + * Request format: + * u32 command (BMI_ROMPATCH_UNINSTALL) + * u32 PatchID + * + * Response format: none + */ + +#define BMI_ROMPATCH_ACTIVATE 11 + /* + * Semantics: Activate a list of previously-installed ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_ACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + +#define BMI_ROMPATCH_DEACTIVATE 12 + /* + * Semantics: Deactivate a list of active ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_DEACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + + +#define BMI_LZ_STREAM_START 13 + /* + * Semantics: Begin an LZ-compressed stream of input + * which is to be uncompressed by the Target to an + * output buffer at address. The output buffer must + * be sufficiently large to hold the uncompressed + * output from the compressed input stream. This BMI + * command should be followed by a series of 1 or more + * BMI_LZ_DATA commands. + * u32 command (BMI_LZ_STREAM_START) + * u32 address + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_LZ_DATA 14 + /* + * Semantics: Host writes AR6K memory with LZ-compressed + * data which is uncompressed by the Target. This command + * must be preceded by a BMI_LZ_STREAM_START command. A series + * of BMI_LZ_DATA commands are considered part of a single + * input stream until another BMI_LZ_STREAM_START is issued. + * Request format: + * u32 command (BMI_LZ_DATA) + * u32 length (of compressed data), + * at most BMI_DATASZ_MAX + * u8 CompressedData[length] + * Response format: none + * Note: Not supported on all versions of ROM firmware. + */ + +#endif /* __BMI_MSG_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h b/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h new file mode 100644 index 000000000000..7a902cb54831 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _CNXMGMT_H_ +#define _CNXMGMT_H_ + +typedef enum { + CM_CONNECT_WITHOUT_SCAN = 0x0001, + CM_CONNECT_ASSOC_POLICY_USER = 0x0002, + CM_CONNECT_SEND_REASSOC = 0x0004, + CM_CONNECT_WITHOUT_ROAMTABLE_UPDATE = 0x0008, + CM_CONNECT_DO_WPA_OFFLOAD = 0x0010, + CM_CONNECT_DO_NOT_DEAUTH = 0x0020, +} CM_CONNECT_TYPE; + +#endif /* _CNXMGMT_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/dbglog.h b/trunk/drivers/staging/ath6kl/include/common/dbglog.h new file mode 100644 index 000000000000..5566e568b83d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/dbglog.h @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DBGLOG_H_ +#define _DBGLOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DBGLOG_TIMESTAMP_OFFSET 0 +#define DBGLOG_TIMESTAMP_MASK 0x0000FFFF /* Bit 0-15. Contains bit + 8-23 of the LF0 timer */ +#define DBGLOG_DBGID_OFFSET 16 +#define DBGLOG_DBGID_MASK 0x03FF0000 /* Bit 16-25 */ +#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */ + +#define DBGLOG_MODULEID_OFFSET 26 +#define DBGLOG_MODULEID_MASK 0x3C000000 /* Bit 26-29 */ +#define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */ + +/* + * Please ensure that the definition of any new module introduced is captured + * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The + * structure is required for the parser to correctly pick up the values for + * different modules. + */ +#define DBGLOG_MODULEID_START +#define DBGLOG_MODULEID_INF 0 +#define DBGLOG_MODULEID_WMI 1 +#define DBGLOG_MODULEID_MISC 2 +#define DBGLOG_MODULEID_PM 3 +#define DBGLOG_MODULEID_TXRX_MGMTBUF 4 +#define DBGLOG_MODULEID_TXRX_TXBUF 5 +#define DBGLOG_MODULEID_TXRX_RXBUF 6 +#define DBGLOG_MODULEID_WOW 7 +#define DBGLOG_MODULEID_WHAL 8 +#define DBGLOG_MODULEID_DC 9 +#define DBGLOG_MODULEID_CO 10 +#define DBGLOG_MODULEID_RO 11 +#define DBGLOG_MODULEID_CM 12 +#define DBGLOG_MODULEID_MGMT 13 +#define DBGLOG_MODULEID_TMR 14 +#define DBGLOG_MODULEID_BTCOEX 15 +#define DBGLOG_MODULEID_END + +#define DBGLOG_NUM_ARGS_OFFSET 30 +#define DBGLOG_NUM_ARGS_MASK 0xC0000000 /* Bit 30-31 */ +#define DBGLOG_NUM_ARGS_MAX 2 /* Upper limit is width of mask */ + +#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0 +#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF + +#define DBGLOG_REPORTING_ENABLED_OFFSET 16 +#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000 + +#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17 +#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000 + +#define DBGLOG_REPORT_SIZE_OFFSET 20 +#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000 + +#define DBGLOG_LOG_BUFFER_SIZE 1500 +#define DBGLOG_DBGID_DEFINITION_LEN_MAX 90 + +PREPACK struct dbglog_buf_s { + struct dbglog_buf_s *next; + u8 *buffer; + u32 bufsize; + u32 length; + u32 count; + u32 free; +} POSTPACK; + +PREPACK struct dbglog_hdr_s { + struct dbglog_buf_s *dbuf; + u32 dropped; +} POSTPACK; + +PREPACK struct dbglog_config_s { + u32 cfgvalid; /* Mask with valid config bits */ + union { + /* TODO: Take care of endianness */ + struct { + u32 mmask:16; /* Mask of modules with logging on */ + u32 rep:1; /* Reporting enabled or not */ + u32 tsr:3; /* Time stamp resolution. Def: 1 ms */ + u32 size:10; /* Report size in number of messages */ + u32 reserved:2; + } dbglog_config; + + u32 value; + } u; +} POSTPACK; + +#define cfgmmask u.dbglog_config.mmask +#define cfgrep u.dbglog_config.rep +#define cfgtsr u.dbglog_config.tsr +#define cfgsize u.dbglog_config.size +#define cfgvalue u.value + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h b/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h new file mode 100644 index 000000000000..15ef829cab20 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h @@ -0,0 +1,558 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DBGLOG_ID_H_ +#define _DBGLOG_ID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The nomenclature for the debug identifiers is MODULE_DESCRIPTION. + * Please ensure that the definition of any new debugid introduced is captured + * between the _DBGID_DEFINITION_START and + * _DBGID_DEFINITION_END defines. The structure is required for the + * parser to correctly pick up the values for different debug identifiers. + */ + +/* INF debug identifier definitions */ +#define INF_DBGID_DEFINITION_START +#define INF_ASSERTION_FAILED 1 +#define INF_TARGET_ID 2 +#define INF_DBGID_DEFINITION_END + +/* WMI debug identifier definitions */ +#define WMI_DBGID_DEFINITION_START +#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1 +#define WMI_EXTENDED_CMD_NOT_HANDLED 2 +#define WMI_CMD_RX_PKT_TOO_SHORT 3 +#define WMI_CALLING_WMI_EXTENSION_FN 4 +#define WMI_CMD_NOT_HANDLED 5 +#define WMI_IN_SYNC 6 +#define WMI_TARGET_WMI_SYNC_CMD 7 +#define WMI_SET_SNR_THRESHOLD_PARAMS 8 +#define WMI_SET_RSSI_THRESHOLD_PARAMS 9 +#define WMI_SET_LQ_TRESHOLD_PARAMS 10 +#define WMI_TARGET_CREATE_PSTREAM_CMD 11 +#define WMI_WI_DTM_INUSE 12 +#define WMI_TARGET_DELETE_PSTREAM_CMD 13 +#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14 +#define WMI_TARGET_GET_BIT_RATE_CMD 15 +#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16 +#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17 +#define WMI_TARGET_GET_TX_PWR_CMD 18 +#define WMI_FREE_EVBUF_WMIBUF 19 +#define WMI_FREE_EVBUF_DATABUF 20 +#define WMI_FREE_EVBUF_BADFLAG 21 +#define WMI_HTC_RX_ERROR_DATA_PACKET 22 +#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23 +#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24 +#define WMI_SENDING_READY_EVENT 25 +#define WMI_SETPOWER_MDOE_TO_MAXPERF 26 +#define WMI_SETPOWER_MDOE_TO_REC 27 +#define WMI_BSSINFO_EVENT_FROM 28 +#define WMI_TARGET_GET_STATS_CMD 29 +#define WMI_SENDING_SCAN_COMPLETE_EVENT 30 +#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31 +#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32 +#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33 +#define WMI_SENDING_ERROR_REPORT_EVENT 34 +#define WMI_SENDING_CAC_EVENT 35 +#define WMI_TARGET_GET_ROAM_TABLE_CMD 36 +#define WMI_TARGET_GET_ROAM_DATA_CMD 37 +#define WMI_SENDING_GPIO_INTR_EVENT 38 +#define WMI_SENDING_GPIO_ACK_EVENT 39 +#define WMI_SENDING_GPIO_DATA_EVENT 40 +#define WMI_CMD_RX 41 +#define WMI_CMD_RX_XTND 42 +#define WMI_EVENT_SEND 43 +#define WMI_EVENT_SEND_XTND 44 +#define WMI_CMD_PARAMS_DUMP_START 45 +#define WMI_CMD_PARAMS_DUMP_END 46 +#define WMI_CMD_PARAMS 47 +#define WMI_DBGID_DEFINITION_END + +/* MISC debug identifier definitions */ +#define MISC_DBGID_DEFINITION_START +#define MISC_WLAN_SCHEDULER_EVENT_REGISTER_ERROR 1 +#define TLPM_INIT 2 +#define TLPM_FILTER_POWER_STATE 3 +#define TLPM_NOTIFY_NOT_IDLE 4 +#define TLPM_TIMEOUT_IDLE_HANDLER 5 +#define TLPM_TIMEOUT_WAKEUP_HANDLER 6 +#define TLPM_WAKEUP_SIGNAL_HANDLER 7 +#define TLPM_UNEXPECTED_GPIO_INTR_ERROR 8 +#define TLPM_BREAK_ON_NOT_RECEIVED_ERROR 9 +#define TLPM_BREAK_OFF_NOT_RECIVED_ERROR 10 +#define TLPM_ACK_GPIO_INTR 11 +#define TLPM_ON 12 +#define TLPM_OFF 13 +#define TLPM_WAKEUP_FROM_HOST 14 +#define TLPM_WAKEUP_FROM_BT 15 +#define TLPM_TX_BREAK_RECIVED 16 +#define TLPM_IDLE_TIMER_NOT_RUNNING 17 +#define MISC_DBGID_DEFINITION_END + +/* TXRX debug identifier definitions */ +#define TXRX_TXBUF_DBGID_DEFINITION_START +#define TXRX_TXBUF_ALLOCATE_BUF 1 +#define TXRX_TXBUF_QUEUE_BUF_TO_MBOX 2 +#define TXRX_TXBUF_QUEUE_BUF_TO_TXQ 3 +#define TXRX_TXBUF_TXQ_DEPTH 4 +#define TXRX_TXBUF_IBSS_QUEUE_TO_SFQ 5 +#define TXRX_TXBUF_IBSS_QUEUE_TO_TXQ_FRM_SFQ 6 +#define TXRX_TXBUF_INITIALIZE_TIMER 7 +#define TXRX_TXBUF_ARM_TIMER 8 +#define TXRX_TXBUF_DISARM_TIMER 9 +#define TXRX_TXBUF_UNINITIALIZE_TIMER 10 +#define TXRX_TXBUF_DBGID_DEFINITION_END + +#define TXRX_RXBUF_DBGID_DEFINITION_START +#define TXRX_RXBUF_ALLOCATE_BUF 1 +#define TXRX_RXBUF_QUEUE_TO_HOST 2 +#define TXRX_RXBUF_QUEUE_TO_WLAN 3 +#define TXRX_RXBUF_ZERO_LEN_BUF 4 +#define TXRX_RXBUF_QUEUE_TO_HOST_LASTBUF_IN_RXCHAIN 5 +#define TXRX_RXBUF_LASTBUF_IN_RXCHAIN_ZEROBUF 6 +#define TXRX_RXBUF_QUEUE_EMPTY_QUEUE_TO_WLAN 7 +#define TXRX_RXBUF_SEND_TO_RECV_MGMT 8 +#define TXRX_RXBUF_SEND_TO_IEEE_LAYER 9 +#define TXRX_RXBUF_REQUEUE_ERROR 10 +#define TXRX_RXBUF_DBGID_DEFINITION_END + +#define TXRX_MGMTBUF_DBGID_DEFINITION_START +#define TXRX_MGMTBUF_ALLOCATE_BUF 1 +#define TXRX_MGMTBUF_ALLOCATE_SM_BUF 2 +#define TXRX_MGMTBUF_ALLOCATE_RMBUF 3 +#define TXRX_MGMTBUF_GET_BUF 4 +#define TXRX_MGMTBUF_GET_SM_BUF 5 +#define TXRX_MGMTBUF_QUEUE_BUF_TO_TXQ 6 +#define TXRX_MGMTBUF_REAPED_BUF 7 +#define TXRX_MGMTBUF_REAPED_SM_BUF 8 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_DRAIN 9 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_SFQ_DRAIN 10 +#define TXRX_MGMTBUF_ENQUEUE_INTO_DATA_SFQ 11 +#define TXRX_MGMTBUF_DEQUEUE_FROM_DATA_SFQ 12 +#define TXRX_MGMTBUF_PAUSE_DATA_TXQ 13 +#define TXRX_MGMTBUF_RESUME_DATA_TXQ 14 +#define TXRX_MGMTBUF_WAIT_FORTXQ_DRAIN_TIMEOUT 15 +#define TXRX_MGMTBUF_DRAINQ 16 +#define TXRX_MGMTBUF_INDICATE_Q_DRAINED 17 +#define TXRX_MGMTBUF_ENQUEUE_INTO_HW_SFQ 18 +#define TXRX_MGMTBUF_DEQUEUE_FROM_HW_SFQ 19 +#define TXRX_MGMTBUF_PAUSE_HW_TXQ 20 +#define TXRX_MGMTBUF_RESUME_HW_TXQ 21 +#define TXRX_MGMTBUF_TEAR_DOWN_BA 22 +#define TXRX_MGMTBUF_PROCESS_ADDBA_REQ 23 +#define TXRX_MGMTBUF_PROCESS_DELBA 24 +#define TXRX_MGMTBUF_PERFORM_BA 25 +#define TXRX_MGMTBUF_WLAN_RESET_ON_ERROR 26 +#define TXRX_MGMTBUF_DBGID_DEFINITION_END + +/* PM (Power Module) debug identifier definitions */ +#define PM_DBGID_DEFINITION_START +#define PM_INIT 1 +#define PM_ENABLE 2 +#define PM_SET_STATE 3 +#define PM_SET_POWERMODE 4 +#define PM_CONN_NOTIFY 5 +#define PM_REF_COUNT_NEGATIVE 6 +#define PM_INFRA_STA_APSD_ENABLE 7 +#define PM_INFRA_STA_UPDATE_APSD_STATE 8 +#define PM_CHAN_OP_REQ 9 +#define PM_SET_MY_BEACON_POLICY 10 +#define PM_SET_ALL_BEACON_POLICY 11 +#define PM_INFRA_STA_SET_PM_PARAMS1 12 +#define PM_INFRA_STA_SET_PM_PARAMS2 13 +#define PM_ADHOC_SET_PM_CAPS_FAIL 14 +#define PM_ADHOC_UNKNOWN_IBSS_ATTRIB_ID 15 +#define PM_ADHOC_SET_PM_PARAMS 16 +#define PM_ADHOC_STATE1 18 +#define PM_ADHOC_STATE2 19 +#define PM_ADHOC_CONN_MAP 20 +#define PM_FAKE_SLEEP 21 +#define PM_AP_STATE1 22 +#define PM_AP_SET_PM_PARAMS 23 +#define PM_DBGID_DEFINITION_END + +/* Wake on Wireless debug identifier definitions */ +#define WOW_DBGID_DEFINITION_START +#define WOW_INIT 1 +#define WOW_GET_CONFIG_DSET 2 +#define WOW_NO_CONFIG_DSET 3 +#define WOW_INVALID_CONFIG_DSET 4 +#define WOW_USE_DEFAULT_CONFIG 5 +#define WOW_SETUP_GPIO 6 +#define WOW_INIT_DONE 7 +#define WOW_SET_GPIO_PIN 8 +#define WOW_CLEAR_GPIO_PIN 9 +#define WOW_SET_WOW_MODE_CMD 10 +#define WOW_SET_HOST_MODE_CMD 11 +#define WOW_ADD_WOW_PATTERN_CMD 12 +#define WOW_NEW_WOW_PATTERN_AT_INDEX 13 +#define WOW_DEL_WOW_PATTERN_CMD 14 +#define WOW_LIST_CONTAINS_PATTERNS 15 +#define WOW_GET_WOW_LIST_CMD 16 +#define WOW_INVALID_FILTER_ID 17 +#define WOW_INVALID_FILTER_LISTID 18 +#define WOW_NO_VALID_FILTER_AT_ID 19 +#define WOW_NO_VALID_LIST_AT_ID 20 +#define WOW_NUM_PATTERNS_EXCEEDED 21 +#define WOW_NUM_LISTS_EXCEEDED 22 +#define WOW_GET_WOW_STATS 23 +#define WOW_CLEAR_WOW_STATS 24 +#define WOW_WAKEUP_HOST 25 +#define WOW_EVENT_WAKEUP_HOST 26 +#define WOW_EVENT_DISCARD 27 +#define WOW_PATTERN_MATCH 28 +#define WOW_PATTERN_NOT_MATCH 29 +#define WOW_PATTERN_NOT_MATCH_OFFSET 30 +#define WOW_DISABLED_HOST_ASLEEP 31 +#define WOW_ENABLED_HOST_ASLEEP_NO_PATTERNS 32 +#define WOW_ENABLED_HOST_ASLEEP_NO_MATCH_FOUND 33 +#define WOW_DBGID_DEFINITION_END + +/* WHAL debug identifier definitions */ +#define WHAL_DBGID_DEFINITION_START +#define WHAL_ERROR_ANI_CONTROL 1 +#define WHAL_ERROR_CHIP_TEST1 2 +#define WHAL_ERROR_CHIP_TEST2 3 +#define WHAL_ERROR_EEPROM_CHECKSUM 4 +#define WHAL_ERROR_EEPROM_MACADDR 5 +#define WHAL_ERROR_INTERRUPT_HIU 6 +#define WHAL_ERROR_KEYCACHE_RESET 7 +#define WHAL_ERROR_KEYCACHE_SET 8 +#define WHAL_ERROR_KEYCACHE_TYPE 9 +#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10 +#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11 +#define WHAL_ERROR_PHY_INVALID_CHANNEL 12 +#define WHAL_ERROR_POWER_AWAKE 13 +#define WHAL_ERROR_POWER_SET 14 +#define WHAL_ERROR_RECV_STOPDMA 15 +#define WHAL_ERROR_RECV_STOPPCU 16 +#define WHAL_ERROR_RESET_CHANNF1 17 +#define WHAL_ERROR_RESET_CHANNF2 18 +#define WHAL_ERROR_RESET_PM 19 +#define WHAL_ERROR_RESET_OFFSETCAL 20 +#define WHAL_ERROR_RESET_RFGRANT 21 +#define WHAL_ERROR_RESET_RXFRAME 22 +#define WHAL_ERROR_RESET_STOPDMA 23 +#define WHAL_ERROR_RESET_RECOVER 24 +#define WHAL_ERROR_XMIT_COMPUTE 25 +#define WHAL_ERROR_XMIT_NOQUEUE 26 +#define WHAL_ERROR_XMIT_ACTIVEQUEUE 27 +#define WHAL_ERROR_XMIT_BADTYPE 28 +#define WHAL_ERROR_XMIT_STOPDMA 29 +#define WHAL_ERROR_INTERRUPT_BB_PANIC 30 +#define WHAL_ERROR_RESET_TXIQCAL 31 +#define WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW 32 +#define WHAL_DBGID_DEFINITION_END + +/* DC debug identifier definitions */ +#define DC_DBGID_DEFINITION_START +#define DC_SCAN_CHAN_START 1 +#define DC_SCAN_CHAN_FINISH 2 +#define DC_BEACON_RECEIVE7 3 +#define DC_SSID_PROBE_CB 4 +#define DC_SEND_NEXT_SSID_PROBE 5 +#define DC_START_SEARCH 6 +#define DC_CANCEL_SEARCH_CB 7 +#define DC_STOP_SEARCH 8 +#define DC_END_SEARCH 9 +#define DC_MIN_CHDWELL_TIMEOUT 10 +#define DC_START_SEARCH_CANCELED 11 +#define DC_SET_POWER_MODE 12 +#define DC_INIT 13 +#define DC_SEARCH_OPPORTUNITY 14 +#define DC_RECEIVED_ANY_BEACON 15 +#define DC_RECEIVED_MY_BEACON 16 +#define DC_PROFILE_IS_ADHOC_BUT_BSS_IS_INFRA 17 +#define DC_PS_ENABLED_BUT_ATHEROS_IE_ABSENT 18 +#define DC_BSS_ADHOC_CHANNEL_NOT_ALLOWED 19 +#define DC_SET_BEACON_UPDATE 20 +#define DC_BEACON_UPDATE_COMPLETE 21 +#define DC_END_SEARCH_BEACON_UPDATE_COMP_CB 22 +#define DC_BSSINFO_EVENT_DROPPED 23 +#define DC_IEEEPS_ENABLED_BUT_ATIM_ABSENT 24 +#define DC_DBGID_DEFINITION_END + +/* CO debug identifier definitions */ +#define CO_DBGID_DEFINITION_START +#define CO_INIT 1 +#define CO_ACQUIRE_LOCK 2 +#define CO_START_OP1 3 +#define CO_START_OP2 4 +#define CO_DRAIN_TX_COMPLETE_CB 5 +#define CO_CHANGE_CHANNEL_CB 6 +#define CO_RETURN_TO_HOME_CHANNEL 7 +#define CO_FINISH_OP_TIMEOUT 8 +#define CO_OP_END 9 +#define CO_CANCEL_OP 10 +#define CO_CHANGE_CHANNEL 11 +#define CO_RELEASE_LOCK 12 +#define CO_CHANGE_STATE 13 +#define CO_DBGID_DEFINITION_END + +/* RO debug identifier definitions */ +#define RO_DBGID_DEFINITION_START +#define RO_REFRESH_ROAM_TABLE 1 +#define RO_UPDATE_ROAM_CANDIDATE 2 +#define RO_UPDATE_ROAM_CANDIDATE_CB 3 +#define RO_UPDATE_ROAM_CANDIDATE_FINISH 4 +#define RO_REFRESH_ROAM_TABLE_DONE 5 +#define RO_PERIODIC_SEARCH_CB 6 +#define RO_PERIODIC_SEARCH_TIMEOUT 7 +#define RO_INIT 8 +#define RO_BMISS_STATE1 9 +#define RO_BMISS_STATE2 10 +#define RO_SET_PERIODIC_SEARCH_ENABLE 11 +#define RO_SET_PERIODIC_SEARCH_DISABLE 12 +#define RO_ENABLE_SQ_THRESHOLD 13 +#define RO_DISABLE_SQ_THRESHOLD 14 +#define RO_ADD_BSS_TO_ROAM_TABLE 15 +#define RO_SET_PERIODIC_SEARCH_MODE 16 +#define RO_CONFIGURE_SQ_THRESHOLD1 17 +#define RO_CONFIGURE_SQ_THRESHOLD2 18 +#define RO_CONFIGURE_SQ_PARAMS 19 +#define RO_LOW_SIGNAL_QUALITY_EVENT 20 +#define RO_HIGH_SIGNAL_QUALITY_EVENT 21 +#define RO_REMOVE_BSS_FROM_ROAM_TABLE 22 +#define RO_UPDATE_CONNECTION_STATE_METRIC 23 +#define RO_DBGID_DEFINITION_END + +/* CM debug identifier definitions */ +#define CM_DBGID_DEFINITION_START +#define CM_INITIATE_HANDOFF 1 +#define CM_INITIATE_HANDOFF_CB 2 +#define CM_CONNECT_EVENT 3 +#define CM_DISCONNECT_EVENT 4 +#define CM_INIT 5 +#define CM_HANDOFF_SOURCE 6 +#define CM_SET_HANDOFF_TRIGGERS 7 +#define CM_CONNECT_REQUEST 8 +#define CM_CONNECT_REQUEST_CB 9 +#define CM_CONTINUE_SCAN_CB 10 +#define CM_DBGID_DEFINITION_END + + +/* mgmt debug identifier definitions */ +#define MGMT_DBGID_DEFINITION_START +#define KEYMGMT_CONNECTION_INIT 1 +#define KEYMGMT_CONNECTION_COMPLETE 2 +#define KEYMGMT_CONNECTION_CLOSE 3 +#define KEYMGMT_ADD_KEY 4 +#define MLME_NEW_STATE 5 +#define MLME_CONN_INIT 6 +#define MLME_CONN_COMPLETE 7 +#define MLME_CONN_CLOSE 8 +#define MGMT_DBGID_DEFINITION_END + +/* TMR debug identifier definitions */ +#define TMR_DBGID_DEFINITION_START +#define TMR_HANG_DETECTED 1 +#define TMR_WDT_TRIGGERED 2 +#define TMR_WDT_RESET 3 +#define TMR_HANDLER_ENTRY 4 +#define TMR_HANDLER_EXIT 5 +#define TMR_SAVED_START 6 +#define TMR_SAVED_END 7 +#define TMR_DBGID_DEFINITION_END + +/* BTCOEX debug identifier definitions */ +#define BTCOEX_DBGID_DEFINITION_START +#define BTCOEX_STATUS_CMD 1 +#define BTCOEX_PARAMS_CMD 2 +#define BTCOEX_ANT_CONFIG 3 +#define BTCOEX_COLOCATED_BT_DEVICE 4 +#define BTCOEX_CLOSE_RANGE_SCO_ON 5 +#define BTCOEX_CLOSE_RANGE_SCO_OFF 6 +#define BTCOEX_CLOSE_RANGE_A2DP_ON 7 +#define BTCOEX_CLOSE_RANGE_A2DP_OFF 8 +#define BTCOEX_A2DP_PROTECT_ON 9 +#define BTCOEX_A2DP_PROTECT_OFF 10 +#define BTCOEX_SCO_PROTECT_ON 11 +#define BTCOEX_SCO_PROTECT_OFF 12 +#define BTCOEX_CLOSE_RANGE_DETECTOR_START 13 +#define BTCOEX_CLOSE_RANGE_DETECTOR_STOP 14 +#define BTCOEX_CLOSE_RANGE_TOGGLE 15 +#define BTCOEX_CLOSE_RANGE_TOGGLE_RSSI_LRCNT 16 +#define BTCOEX_CLOSE_RANGE_RSSI_THRESH 17 +#define BTCOEX_CLOSE_RANGE_LOW_RATE_THRESH 18 +#define BTCOEX_PTA_PRI_INTR_HANDLER 19 +#define BTCOEX_PSPOLL_QUEUED 20 +#define BTCOEX_PSPOLL_COMPLETE 21 +#define BTCOEX_DBG_PM_AWAKE 22 +#define BTCOEX_DBG_PM_SLEEP 23 +#define BTCOEX_DBG_SCO_COEX_ON 24 +#define BTCOEX_SCO_DATARECEIVE 25 +#define BTCOEX_INTR_INIT 26 +#define BTCOEX_PTA_PRI_DIFF 27 +#define BTCOEX_TIM_NOTIFICATION 28 +#define BTCOEX_SCO_WAKEUP_ON_DATA 29 +#define BTCOEX_SCO_SLEEP 30 +#define BTCOEX_SET_WEIGHTS 31 +#define BTCOEX_SCO_DATARECEIVE_LATENCY_VAL 32 +#define BTCOEX_SCO_MEASURE_TIME_DIFF 33 +#define BTCOEX_SET_EOL_VAL 34 +#define BTCOEX_OPT_DETECT_HANDLER 35 +#define BTCOEX_SCO_TOGGLE_STATE 36 +#define BTCOEX_SCO_STOMP 37 +#define BTCOEX_NULL_COMP_CALLBACK 38 +#define BTCOEX_RX_INCOMING 39 +#define BTCOEX_RX_INCOMING_CTL 40 +#define BTCOEX_RX_INCOMING_MGMT 41 +#define BTCOEX_RX_INCOMING_DATA 42 +#define BTCOEX_RTS_RECEPTION 43 +#define BTCOEX_FRAME_PRI_LOW_RATE_THRES 44 +#define BTCOEX_PM_FAKE_SLEEP 45 +#define BTCOEX_ACL_COEX_STATUS 46 +#define BTCOEX_ACL_COEX_DETECTION 47 +#define BTCOEX_A2DP_COEX_STATUS 48 +#define BTCOEX_SCO_STATUS 49 +#define BTCOEX_WAKEUP_ON_DATA 50 +#define BTCOEX_DATARECEIVE 51 +#define BTCOEX_GET_MAX_AGGR_SIZE 53 +#define BTCOEX_MAX_AGGR_AVAIL_TIME 54 +#define BTCOEX_DBG_WBTIMER_INTR 55 +#define BTCOEX_DBG_SCO_SYNC 57 +#define BTCOEX_UPLINK_QUEUED_RATE 59 +#define BTCOEX_DBG_UPLINK_ENABLE_EOL 60 +#define BTCOEX_UPLINK_FRAME_DURATION 61 +#define BTCOEX_UPLINK_SET_EOL 62 +#define BTCOEX_DBG_EOL_EXPIRED 63 +#define BTCOEX_DBG_DATA_COMPLETE 64 +#define BTCOEX_UPLINK_QUEUED_TIMESTAMP 65 +#define BTCOEX_DBG_DATA_COMPLETE_TIME 66 +#define BTCOEX_DBG_A2DP_ROLE_IS_SLAVE 67 +#define BTCOEX_DBG_A2DP_ROLE_IS_MASTER 68 +#define BTCOEX_DBG_UPLINK_SEQ_NUM 69 +#define BTCOEX_UPLINK_AGGR_SEQ 70 +#define BTCOEX_DBG_TX_COMP_SEQ_NO 71 +#define BTCOEX_DBG_MAX_AGGR_PAUSE_STATE 72 +#define BTCOEX_DBG_ACL_TRAFFIC 73 +#define BTCOEX_CURR_AGGR_PROP 74 +#define BTCOEX_DBG_SCO_GET_PER_TIME_DIFF 75 +#define BTCOEX_PSPOLL_PROCESS 76 +#define BTCOEX_RETURN_FROM_MAC 77 +#define BTCOEX_FREED_REQUEUED_CNT 78 +#define BTCOEX_DBG_TOGGLE_LOW_RATES 79 +#define BTCOEX_MAC_GOES_TO_SLEEP 80 +#define BTCOEX_DBG_A2DP_NO_SYNC 81 +#define BTCOEX_RETURN_FROM_MAC_HOLD_Q_INFO 82 +#define BTCOEX_RETURN_FROM_MAC_AC 83 +#define BTCOEX_DBG_DTIM_RECV 84 +#define BTCOEX_IS_PRE_UPDATE 86 +#define BTCOEX_ENQUEUED_BIT_MAP 87 +#define BTCOEX_TX_COMPLETE_FIRST_DESC_STATS 88 +#define BTCOEX_UPLINK_DESC 89 +#define BTCOEX_SCO_GET_PER_FIRST_FRM_TIMESTAMP 90 +#define BTCOEX_DBG_RECV_ACK 94 +#define BTCOEX_DBG_ADDBA_INDICATION 95 +#define BTCOEX_TX_COMPLETE_EOL_FAILED 96 +#define BTCOEX_DBG_A2DP_USAGE_COMPLETE 97 +#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_HANDLER 98 +#define BTCOEX_DBG_A2DP_SYNC_INTR 99 +#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_RECEPTION 100 +#define BTCOEX_FORM_AGGR_CURR_AGGR 101 +#define BTCOEX_DBG_TOGGLE_A2DP_BURST_CNT 102 +#define BTCOEX_DBG_BT_TRAFFIC 103 +#define BTCOEX_DBG_STOMP_BT_TRAFFIC 104 +#define BTCOEX_RECV_NULL 105 +#define BTCOEX_DBG_A2DP_MASTER_BT_END 106 +#define BTCOEX_DBG_A2DP_BT_START 107 +#define BTCOEX_DBG_A2DP_SLAVE_BT_END 108 +#define BTCOEX_DBG_A2DP_STOMP_BT 109 +#define BTCOEX_DBG_GO_TO_SLEEP 110 +#define BTCOEX_DBG_A2DP_PKT 111 +#define BTCOEX_DBG_A2DP_PSPOLL_DATA_RECV 112 +#define BTCOEX_DBG_A2DP_NULL 113 +#define BTCOEX_DBG_UPLINK_DATA 114 +#define BTCOEX_DBG_A2DP_STOMP_LOW_PRIO_NULL 115 +#define BTCOEX_DBG_ADD_BA_RESP_TIMEOUT 116 +#define BTCOEX_DBG_TXQ_STATE 117 +#define BTCOEX_DBG_ALLOW_SCAN 118 +#define BTCOEX_DBG_SCAN_REQUEST 119 +#define BTCOEX_A2DP_SLEEP 127 +#define BTCOEX_DBG_DATA_ACTIV_TIMEOUT 128 +#define BTCOEX_DBG_SWITCH_TO_PSPOLL_ON_MODE 129 +#define BTCOEX_DBG_SWITCH_TO_PSPOLL_OFF_MODE 130 +#define BTCOEX_DATARECEIVE_AGGR 131 +#define BTCOEX_DBG_DATA_RECV_SLEEPING_PENDING 132 +#define BTCOEX_DBG_DATARESP_TIMEOUT 133 +#define BTCOEX_BDG_BMISS 134 +#define BTCOEX_DBG_DATA_RECV_WAKEUP_TIM 135 +#define BTCOEX_DBG_SECOND_BMISS 136 +#define BTCOEX_DBG_SET_WLAN_STATE 138 +#define BTCOEX_BDG_FIRST_BMISS 139 +#define BTCOEX_DBG_A2DP_CHAN_OP 140 +#define BTCOEX_DBG_A2DP_INTR 141 +#define BTCOEX_DBG_BT_INQUIRY 142 +#define BTCOEX_DBG_BT_INQUIRY_DATA_FETCH 143 +#define BTCOEX_DBG_POST_INQUIRY_FINISH 144 +#define BTCOEX_DBG_SCO_OPT_MODE_TIMER_HANDLER 145 +#define BTCOEX_DBG_NULL_FRAME_SLEEP 146 +#define BTCOEX_DBG_NULL_FRAME_AWAKE 147 +#define BTCOEX_DBG_SET_AGGR_SIZE 152 +#define BTCOEX_DBG_TEAR_BA_TIMEOUT 153 +#define BTCOEX_DBG_MGMT_FRAME_SEQ_NO 154 +#define BTCOEX_DBG_SCO_STOMP_HIGH_PRI 155 +#define BTCOEX_DBG_COLOCATED_BT_DEV 156 +#define BTCOEX_DBG_FE_ANT_TYPE 157 +#define BTCOEX_DBG_BT_INQUIRY_CMD 158 +#define BTCOEX_DBG_SCO_CONFIG 159 +#define BTCOEX_DBG_SCO_PSPOLL_CONFIG 160 +#define BTCOEX_DBG_SCO_OPTMODE_CONFIG 161 +#define BTCOEX_DBG_A2DP_CONFIG 162 +#define BTCOEX_DBG_A2DP_PSPOLL_CONFIG 163 +#define BTCOEX_DBG_A2DP_OPTMODE_CONFIG 164 +#define BTCOEX_DBG_ACLCOEX_CONFIG 165 +#define BTCOEX_DBG_ACLCOEX_PSPOLL_CONFIG 166 +#define BTCOEX_DBG_ACLCOEX_OPTMODE_CONFIG 167 +#define BTCOEX_DBG_DEBUG_CMD 168 +#define BTCOEX_DBG_SET_BT_OPERATING_STATUS 169 +#define BTCOEX_DBG_GET_CONFIG 170 +#define BTCOEX_DBG_GET_STATS 171 +#define BTCOEX_DBG_BT_OPERATING_STATUS 172 +#define BTCOEX_DBG_PERFORM_RECONNECT 173 +#define BTCOEX_DBG_ACL_WLAN_MED 175 +#define BTCOEX_DBG_ACL_BT_MED 176 +#define BTCOEX_DBG_WLAN_CONNECT 177 +#define BTCOEX_DBG_A2DP_DUAL_START 178 +#define BTCOEX_DBG_PMAWAKE_NOTIFY 179 +#define BTCOEX_DBG_BEACON_SCAN_ENABLE 180 +#define BTCOEX_DBG_BEACON_SCAN_DISABLE 181 +#define BTCOEX_DBG_RX_NOTIFY 182 +#define BTCOEX_SCO_GET_PER_SECOND_FRM_TIMESTAMP 183 +#define BTCOEX_DBG_TXQ_DETAILS 184 +#define BTCOEX_DBG_SCO_STOMP_LOW_PRI 185 +#define BTCOEX_DBG_A2DP_FORCE_SCAN 186 +#define BTCOEX_DBG_DTIM_STOMP_COMP 187 +#define BTCOEX_ACL_PRESENCE_TIMER 188 +#define BTCOEX_DBGID_DEFINITION_END + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_ID_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/discovery.h b/trunk/drivers/staging/ath6kl/include/common/discovery.h new file mode 100644 index 000000000000..da1b33245069 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/discovery.h @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DISCOVERY_H_ +#define _DISCOVERY_H_ + +/* + * DC_SCAN_PRIORITY is an 8-bit bitmap of the scan priority of a channel + */ +typedef enum { + DEFAULT_SCPRI = 0x01, + POPULAR_SCPRI = 0x02, + SSIDS_SCPRI = 0x04, + PROF_SCPRI = 0x08, +} DC_SCAN_PRIORITY; + +/* The following search type construct can be used to manipulate the behavior of the search module based on different bits set */ +typedef enum { + SCAN_RESET = 0, + SCAN_ALL = (DEFAULT_SCPRI | POPULAR_SCPRI | \ + SSIDS_SCPRI | PROF_SCPRI), + + SCAN_POPULAR = (POPULAR_SCPRI | SSIDS_SCPRI | PROF_SCPRI), + SCAN_SSIDS = (SSIDS_SCPRI | PROF_SCPRI), + SCAN_PROF_MASK = (PROF_SCPRI), + SCAN_MULTI_CHANNEL = 0x000100, + SCAN_DETERMINISTIC = 0x000200, + SCAN_PROFILE_MATCH_TERMINATED = 0x000400, + SCAN_HOME_CHANNEL_SKIP = 0x000800, + SCAN_CHANNEL_LIST_CONTINUE = 0x001000, + SCAN_CURRENT_SSID_SKIP = 0x002000, + SCAN_ACTIVE_PROBE_DISABLE = 0x004000, + SCAN_CHANNEL_HINT_ONLY = 0x008000, + SCAN_ACTIVE_CHANNELS_ONLY = 0x010000, + SCAN_UNUSED1 = 0x020000, /* unused */ + SCAN_PERIODIC = 0x040000, + SCAN_FIXED_DURATION = 0x080000, + SCAN_AP_ASSISTED = 0x100000, +} DC_SCAN_TYPE; + +typedef enum { + BSS_REPORTING_DEFAULT = 0x0, + EXCLUDE_NON_SCAN_RESULTS = 0x1, /* Exclude results outside of scan */ +} DC_BSS_REPORTING_POLICY; + +typedef enum { + DC_IGNORE_WPAx_GROUP_CIPHER = 0x01, + DC_PROFILE_MATCH_DONE = 0x02, + DC_IGNORE_AAC_BEACON = 0x04, + DC_CSA_FOLLOW_BSS = 0x08, +} DC_PROFILE_FILTER; + +#define DEFAULT_DC_PROFILE_FILTER (DC_CSA_FOLLOW_BSS) + +#endif /* _DISCOVERY_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/epping_test.h b/trunk/drivers/staging/ath6kl/include/common/epping_test.h new file mode 100644 index 000000000000..9eb5fdfa746a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/epping_test.h @@ -0,0 +1,111 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +// + +/* This file contains shared definitions for the host/target endpoint ping test */ + +#ifndef EPPING_TEST_H_ +#define EPPING_TEST_H_ + + /* alignment to 4-bytes */ +#define EPPING_ALIGNMENT_PAD (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) - sizeof(struct htc_frame_hdr)) + +#ifndef A_OFFSETOF +#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field)) +#endif + +#define EPPING_RSVD_FILL 0xCC + +#define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET 7 + +typedef PREPACK struct { + u8 _HCIRsvd[8]; /* reserved for HCI packet header (GMBOX) testing */ + u8 StreamEcho_h; /* stream no. to echo this packet on (filled by host) */ + u8 StreamEchoSent_t; /* stream no. packet was echoed to (filled by target) + When echoed: StreamEchoSent_t == StreamEcho_h */ + u8 StreamRecv_t; /* stream no. that target received this packet on (filled by target) */ + u8 StreamNo_h; /* stream number to send on (filled by host) */ + u8 Magic_h[4]; /* magic number to filter for this packet on the host*/ + u8 _rsvd[6]; /* reserved fields that must be set to a "reserved" value + since this packet maps to a 14-byte ethernet frame we want + to make sure ethertype field is set to something unknown */ + + u8 _pad[2]; /* padding for alignment */ + u8 TimeStamp[8]; /* timestamp of packet (host or target) */ + u32 HostContext_h; /* 4 byte host context, target echos this back */ + u32 SeqNo; /* sequence number (set by host or target) */ + u16 Cmd_h; /* ping command (filled by host) */ + u16 CmdFlags_h; /* optional flags */ + u8 CmdBuffer_h[8]; /* buffer for command (host -> target) */ + u8 CmdBuffer_t[8]; /* buffer for command (target -> host) */ + u16 DataLength; /* length of data */ + u16 DataCRC; /* 16 bit CRC of data */ + u16 HeaderCRC; /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */ +} POSTPACK EPPING_HEADER; + +#define EPPING_PING_MAGIC_0 0xAA +#define EPPING_PING_MAGIC_1 0x55 +#define EPPING_PING_MAGIC_2 0xCE +#define EPPING_PING_MAGIC_3 0xEC + + + +#define IS_EPPING_PACKET(pPkt) (((pPkt)->Magic_h[0] == EPPING_PING_MAGIC_0) && \ + ((pPkt)->Magic_h[1] == EPPING_PING_MAGIC_1) && \ + ((pPkt)->Magic_h[2] == EPPING_PING_MAGIC_2) && \ + ((pPkt)->Magic_h[3] == EPPING_PING_MAGIC_3)) + +#define SET_EPPING_PACKET_MAGIC(pPkt) { (pPkt)->Magic_h[0] = EPPING_PING_MAGIC_0; \ + (pPkt)->Magic_h[1] = EPPING_PING_MAGIC_1; \ + (pPkt)->Magic_h[2] = EPPING_PING_MAGIC_2; \ + (pPkt)->Magic_h[3] = EPPING_PING_MAGIC_3;} + +#define CMD_FLAGS_DATA_CRC (1 << 0) /* DataCRC field is valid */ +#define CMD_FLAGS_DELAY_ECHO (1 << 1) /* delay the echo of the packet */ +#define CMD_FLAGS_NO_DROP (1 << 2) /* do not drop at HTC layer no matter what the stream is */ + +#define IS_EPING_PACKET_NO_DROP(pPkt) ((pPkt)->CmdFlags_h & CMD_FLAGS_NO_DROP) + +#define EPPING_CMD_ECHO_PACKET 1 /* echo packet test */ +#define EPPING_CMD_RESET_RECV_CNT 2 /* reset recv count */ +#define EPPING_CMD_CAPTURE_RECV_CNT 3 /* fetch recv count, 4-byte count returned in CmdBuffer_t */ +#define EPPING_CMD_NO_ECHO 4 /* non-echo packet test (tx-only) */ +#define EPPING_CMD_CONT_RX_START 5 /* continuous RX packets, parameters are in CmdBuffer_h */ +#define EPPING_CMD_CONT_RX_STOP 6 /* stop continuous RX packet transmission */ + + /* test command parameters may be no more than 8 bytes */ +typedef PREPACK struct { + u16 BurstCnt; /* number of packets to burst together (for HTC 2.1 testing) */ + u16 PacketLength; /* length of packet to generate including header */ + u16 Flags; /* flags */ + +#define EPPING_CONT_RX_DATA_CRC (1 << 0) /* Add CRC to all data */ +#define EPPING_CONT_RX_RANDOM_DATA (1 << 1) /* randomize the data pattern */ +#define EPPING_CONT_RX_RANDOM_LEN (1 << 2) /* randomize the packet lengths */ +} POSTPACK EPPING_CONT_RX_PARAMS; + +#define EPPING_HDR_CRC_OFFSET A_OFFSETOF(EPPING_HEADER,StreamNo_h) +#define EPPING_HDR_BYTES_CRC (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(u16))) + +#define HCI_TRANSPORT_STREAM_NUM 16 /* this number is higher than the define WMM AC classes so we + can use this to distinguish packets */ + +#endif /*EPPING_TEST_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/common/gmboxif.h b/trunk/drivers/staging/ath6kl/include/common/gmboxif.h new file mode 100644 index 000000000000..ea11c14def43 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/gmboxif.h @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __GMBOXIF_H__ +#define __GMBOXIF_H__ + +/* GMBOX interface definitions */ + +#define AR6K_GMBOX_CREDIT_COUNTER 1 /* we use credit counter 1 to track credits */ +#define AR6K_GMBOX_CREDIT_SIZE_COUNTER 2 /* credit counter 2 is used to pass the size of each credit */ + + + /* HCI UART transport definitions when used over GMBOX interface */ +#define HCI_UART_COMMAND_PKT 0x01 +#define HCI_UART_ACL_PKT 0x02 +#define HCI_UART_SCO_PKT 0x03 +#define HCI_UART_EVENT_PKT 0x04 + + /* definitions for BT HCI packets */ +typedef PREPACK struct { + u16 Flags_ConnHandle; + u16 Length; +} POSTPACK BT_HCI_ACL_HEADER; + +typedef PREPACK struct { + u16 Flags_ConnHandle; + u8 Length; +} POSTPACK BT_HCI_SCO_HEADER; + +typedef PREPACK struct { + u16 OpCode; + u8 ParamLength; +} POSTPACK BT_HCI_COMMAND_HEADER; + +typedef PREPACK struct { + u8 EventCode; + u8 ParamLength; +} POSTPACK BT_HCI_EVENT_HEADER; + +/* MBOX host interrupt signal assignments */ + +#define MBOX_SIG_HCI_BRIDGE_MAX 8 +#define MBOX_SIG_HCI_BRIDGE_BT_ON 0 +#define MBOX_SIG_HCI_BRIDGE_BT_OFF 1 +#define MBOX_SIG_HCI_BRIDGE_BAUD_SET 2 +#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON 3 +#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF 4 + + +#endif /* __GMBOXIF_H__ */ + diff --git a/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h b/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h new file mode 100644 index 000000000000..f9d425d48dc2 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h @@ -0,0 +1,9 @@ +#ifndef _GPIO_REG_REG_H_ +#define _GPIO_REG_REG_H_ + +#define GPIO_PIN10_ADDRESS 0x00000050 +#define GPIO_PIN11_ADDRESS 0x00000054 +#define GPIO_PIN12_ADDRESS 0x00000058 +#define GPIO_PIN13_ADDRESS 0x0000005c + +#endif /* _GPIO_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/htc.h b/trunk/drivers/staging/ath6kl/include/common/htc.h new file mode 100644 index 000000000000..85cbfa89d670 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/htc.h @@ -0,0 +1,227 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_H__ +#define __HTC_H__ + +#define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field)) + +#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \ + (((u16)(((u8 *)(p))[(highbyte)])) << 8 | (u16)(((u8 *)(p))[(lowbyte)])) + +/* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a + * structure using only the type and field name. + * Use these macros if there is the potential for unaligned buffer accesses. */ +#define A_GET_UINT16_FIELD(p,type,field) \ + ASSEMBLE_UNALIGNED_UINT16(p,\ + A_OFFSETOF(type,field) + 1, \ + A_OFFSETOF(type,field)) + +#define A_SET_UINT16_FIELD(p,type,field,value) \ +{ \ + ((u8 *)(p))[A_OFFSETOF(type,field)] = (u8)(value); \ + ((u8 *)(p))[A_OFFSETOF(type,field) + 1] = (u8)((value) >> 8); \ +} + +#define A_GET_UINT8_FIELD(p,type,field) \ + ((u8 *)(p))[A_OFFSETOF(type,field)] + +#define A_SET_UINT8_FIELD(p,type,field,value) \ + ((u8 *)(p))[A_OFFSETOF(type,field)] = (value) + +/****** DANGER DANGER *************** + * + * The frame header length and message formats defined herein were + * selected to accommodate optimal alignment for target processing. This reduces code + * size and improves performance. + * + * Any changes to the header length may alter the alignment and cause exceptions + * on the target. When adding to the message structures insure that fields are + * properly aligned. + * + */ + +/* HTC frame header */ +PREPACK struct htc_frame_hdr { + /* do not remove or re-arrange these fields, these are minimally required + * to take advantage of 4-byte lookaheads in some hardware implementations */ + u8 EndpointID; + u8 Flags; + u16 PayloadLen; /* length of data (including trailer) that follows the header */ + + /***** end of 4-byte lookahead ****/ + + u8 ControlBytes[2]; + + /* message payload starts after the header */ + +} POSTPACK; + +/* frame header flags */ + + /* send direction */ +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) +#define HTC_FLAGS_SEND_BUNDLE (1 << 1) /* start or part of bundle */ + /* receive direction */ +#define HTC_FLAGS_RECV_UNUSED_0 (1 << 0) /* bit 0 unused */ +#define HTC_FLAGS_RECV_TRAILER (1 << 1) /* bit 1 trailer data present */ +#define HTC_FLAGS_RECV_UNUSED_2 (1 << 0) /* bit 2 unused */ +#define HTC_FLAGS_RECV_UNUSED_3 (1 << 0) /* bit 3 unused */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0) /* bits 7..4 */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 4 + +#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr)) +#define HTC_MAX_TRAILER_LENGTH 255 +#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr)) + +/* HTC control message IDs */ + +#define HTC_MSG_READY_ID 1 +#define HTC_MSG_CONNECT_SERVICE_ID 2 +#define HTC_MSG_CONNECT_SERVICE_RESPONSE_ID 3 +#define HTC_MSG_SETUP_COMPLETE_ID 4 +#define HTC_MSG_SETUP_COMPLETE_EX_ID 5 + +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256 + +/* base message ID header */ +typedef PREPACK struct { + u16 MessageID; +} POSTPACK HTC_UNKNOWN_MSG; + +/* HTC ready message + * direction : target-to-host */ +typedef PREPACK struct { + u16 MessageID; /* ID */ + u16 CreditCount; /* number of credits the target can offer */ + u16 CreditSize; /* size of each credit */ + u8 MaxEndpoints; /* maximum number of endpoints the target has resources for */ + u8 _Pad1; +} POSTPACK HTC_READY_MSG; + + /* extended HTC ready message */ +typedef PREPACK struct { + HTC_READY_MSG Version2_0_Info; /* legacy version 2.0 information at the front... */ + /* extended information */ + u8 HTCVersion; + u8 MaxMsgsPerHTCBundle; +} POSTPACK HTC_READY_EX_MSG; + +#define HTC_VERSION_2P0 0x00 +#define HTC_VERSION_2P1 0x01 /* HTC 2.1 */ + +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128 + +/* connect service + * direction : host-to-target */ +typedef PREPACK struct { + u16 MessageID; + u16 ServiceID; /* service ID of the service to connect to */ + u16 ConnectionFlags; /* connection flags */ + +#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when + the host needs credits */ +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3) +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3 + + u8 ServiceMetaLength; /* length of meta data that follows */ + u8 _Pad1; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_MSG; + +/* connect response + * direction : target-to-host */ +typedef PREPACK struct { + u16 MessageID; + u16 ServiceID; /* service ID that the connection request was made */ + u8 Status; /* service connection status */ + u8 EndpointID; /* assigned endpoint ID */ + u16 MaxMsgSize; /* maximum expected message size on this endpoint */ + u8 ServiceMetaLength; /* length of meta data that follows */ + u8 _Pad1; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG; + +typedef PREPACK struct { + u16 MessageID; + /* currently, no other fields */ +} POSTPACK HTC_SETUP_COMPLETE_MSG; + + /* extended setup completion message */ +typedef PREPACK struct { + u16 MessageID; + u32 SetupFlags; + u8 MaxMsgsPerBundledRecv; + u8 Rsvd[3]; +} POSTPACK HTC_SETUP_COMPLETE_EX_MSG; + +#define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV (1 << 0) + +/* connect response status codes */ +#define HTC_SERVICE_SUCCESS 0 /* success */ +#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */ +#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */ +#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */ +#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more + endpoints */ + +/* report record IDs */ + +#define HTC_RECORD_NULL 0 +#define HTC_RECORD_CREDITS 1 +#define HTC_RECORD_LOOKAHEAD 2 +#define HTC_RECORD_LOOKAHEAD_BUNDLE 3 + +typedef PREPACK struct { + u8 RecordID; /* Record ID */ + u8 Length; /* Length of record */ +} POSTPACK HTC_RECORD_HDR; + +typedef PREPACK struct { + u8 EndpointID; /* Endpoint that owns these credits */ + u8 Credits; /* credits to report since last report */ +} POSTPACK HTC_CREDIT_REPORT; + +typedef PREPACK struct { + u8 PreValid; /* pre valid guard */ + u8 LookAhead[4]; /* 4 byte lookahead */ + u8 PostValid; /* post valid guard */ + + /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes. + * The PreValid bytes must equal the inverse of the PostValid byte */ + +} POSTPACK HTC_LOOKAHEAD_REPORT; + +typedef PREPACK struct { + u8 LookAhead[4]; /* 4 byte lookahead */ +} POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT; + +#endif /* __HTC_H__ */ + diff --git a/trunk/drivers/staging/ath6kl/include/common/htc_services.h b/trunk/drivers/staging/ath6kl/include/common/htc_services.h new file mode 100644 index 000000000000..fb22268a8d84 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/htc_services.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_SERVICES_H__ +#define __HTC_SERVICES_H__ + +/* Current service IDs */ + +typedef enum { + RSVD_SERVICE_GROUP = 0, + WMI_SERVICE_GROUP = 1, + + HTC_TEST_GROUP = 254, + HTC_SERVICE_GROUP_LAST = 255 +}HTC_SERVICE_GROUP_IDS; + +#define MAKE_SERVICE_ID(group,index) \ + (int)(((int)group << 8) | (int)(index)) + +/* NOTE: service ID of 0x0000 is reserved and should never be used */ +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1) +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0) +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1) +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2) +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3) +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4) +#define WMI_MAX_SERVICES 5 + +/* raw stream service (i.e. flash, tcmd, calibration apps) */ +#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0) + +#endif /*HTC_SERVICES_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/common/pkt_log.h b/trunk/drivers/staging/ath6kl/include/common/pkt_log.h new file mode 100644 index 000000000000..a3719adf54ca --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/pkt_log.h @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2005-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __PKT_LOG_H__ +#define __PKT_LOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Pkt log info */ +typedef PREPACK struct pkt_log_t { + struct info_t { + u16 st; + u16 end; + u16 cur; + }info[4096]; + u16 last_idx; +}POSTPACK PACKET_LOG; + + +#ifdef __cplusplus +} +#endif +#endif /* __PKT_LOG_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/roaming.h b/trunk/drivers/staging/ath6kl/include/common/roaming.h new file mode 100644 index 000000000000..8019850a0571 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/roaming.h @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _ROAMING_H_ +#define _ROAMING_H_ + +/* + * The signal quality could be in terms of either snr or rssi. We should + * have an enum for both of them. For the time being, we are going to move + * it to wmi.h that is shared by both host and the target, since we are + * repartitioning the code to the host + */ +#define SIGNAL_QUALITY_NOISE_FLOOR -96 +#define SIGNAL_QUALITY_METRICS_NUM_MAX 2 +typedef enum { + SIGNAL_QUALITY_METRICS_SNR = 0, + SIGNAL_QUALITY_METRICS_RSSI, + SIGNAL_QUALITY_METRICS_ALL, +} SIGNAL_QUALITY_METRICS_TYPE; + +#endif /* _ROAMING_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/targaddrs.h b/trunk/drivers/staging/ath6kl/include/common/targaddrs.h new file mode 100644 index 000000000000..c866cefbd8fd --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/targaddrs.h @@ -0,0 +1,395 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __TARGADDRS_H__ +#define __TARGADDRS_H__ + +#if defined(AR6002) +#include "AR6002/addrs.h" +#endif + +/* + * AR6K option bits, to enable/disable various features. + * By default, all option bits are 0. + * These bits can be set in LOCAL_SCRATCH register 0. + */ +#define AR6K_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */ +#define AR6K_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */ +#define AR6K_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */ +#define AR6K_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */ +#define AR6K_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */ +#define AR6K_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */ +#define AR6K_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */ +#define AR6K_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */ + +/* + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the + * host_interest structure. It must match the address of the _host_interest + * symbol (see linker script). + * + * Host Interest is shared between Host and Target in order to coordinate + * between the two, and is intended to remain constant (with additions only + * at the end) across software releases. + * + * All addresses are available here so that it's possible to + * write a single binary that works with all Target Types. + * May be used in assembler code as well as C. + */ +#define AR6002_HOST_INTEREST_ADDRESS 0x00500400 +#define AR6003_HOST_INTEREST_ADDRESS 0x00540600 + + +#define HOST_INTEREST_MAX_SIZE 0x100 + +#if !defined(__ASSEMBLER__) +struct register_dump_s; +struct dbglog_hdr_s; + +/* + * These are items that the Host may need to access + * via BMI or via the Diagnostic Window. The position + * of items in this structure must remain constant + * across firmware revisions! + * + * Types for each item must be fixed size across + * target and host platforms. + * + * More items may be added at the end. + */ +PREPACK struct host_interest_s { + /* + * Pointer to application-defined area, if any. + * Set by Target application during startup. + */ + u32 hi_app_host_interest; /* 0x00 */ + + /* Pointer to register dump area, valid after Target crash. */ + u32 hi_failure_state; /* 0x04 */ + + /* Pointer to debug logging header */ + u32 hi_dbglog_hdr; /* 0x08 */ + + u32 hi_unused1; /* 0x0c */ + + /* + * General-purpose flag bits, similar to AR6000_OPTION_* flags. + * Can be used by application rather than by OS. + */ + u32 hi_option_flag; /* 0x10 */ + + /* + * Boolean that determines whether or not to + * display messages on the serial port. + */ + u32 hi_serial_enable; /* 0x14 */ + + /* Start address of DataSet index, if any */ + u32 hi_dset_list_head; /* 0x18 */ + + /* Override Target application start address */ + u32 hi_app_start; /* 0x1c */ + + /* Clock and voltage tuning */ + u32 hi_skip_clock_init; /* 0x20 */ + u32 hi_core_clock_setting; /* 0x24 */ + u32 hi_cpu_clock_setting; /* 0x28 */ + u32 hi_system_sleep_setting; /* 0x2c */ + u32 hi_xtal_control_setting; /* 0x30 */ + u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ + u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ + u32 hi_ref_voltage_trim_setting; /* 0x3c */ + u32 hi_clock_info; /* 0x40 */ + + /* + * Flash configuration overrides, used only + * when firmware is not executing from flash. + * (When using flash, modify the global variables + * with equivalent names.) + */ + u32 hi_bank0_addr_value; /* 0x44 */ + u32 hi_bank0_read_value; /* 0x48 */ + u32 hi_bank0_write_value; /* 0x4c */ + u32 hi_bank0_config_value; /* 0x50 */ + + /* Pointer to Board Data */ + u32 hi_board_data; /* 0x54 */ + u32 hi_board_data_initialized; /* 0x58 */ + + u32 hi_dset_RAM_index_table; /* 0x5c */ + + u32 hi_desired_baud_rate; /* 0x60 */ + u32 hi_dbglog_config; /* 0x64 */ + u32 hi_end_RAM_reserve_sz; /* 0x68 */ + u32 hi_mbox_io_block_sz; /* 0x6c */ + + u32 hi_num_bpatch_streams; /* 0x70 -- unused */ + u32 hi_mbox_isr_yield_limit; /* 0x74 */ + + u32 hi_refclk_hz; /* 0x78 */ + u32 hi_ext_clk_detected; /* 0x7c */ + u32 hi_dbg_uart_txpin; /* 0x80 */ + u32 hi_dbg_uart_rxpin; /* 0x84 */ + u32 hi_hci_uart_baud; /* 0x88 */ + u32 hi_hci_uart_pin_assignments; /* 0x8C */ + /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */ + u32 hi_hci_uart_baud_scale_val; /* 0x90 */ + u32 hi_hci_uart_baud_step_val; /* 0x94 */ + + u32 hi_allocram_start; /* 0x98 */ + u32 hi_allocram_sz; /* 0x9c */ + u32 hi_hci_bridge_flags; /* 0xa0 */ + u32 hi_hci_uart_support_pins; /* 0xa4 */ + /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */ + u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */ + /* + * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high + * [31:16]: wakeup timeout in ms + */ + + /* Pointer to extended board data */ + u32 hi_board_ext_data; /* 0xac */ + u32 hi_board_ext_data_config; /* 0xb0 */ + + /* + * Bit [0] : valid + * Bit[31:16: size + */ + /* + * hi_reset_flag is used to do some stuff when target reset. + * such as restore app_start after warm reset or + * preserve host Interest area, or preserve ROM data, literals etc. + */ + u32 hi_reset_flag; /* 0xb4 */ + /* indicate hi_reset_flag is valid */ + u32 hi_reset_flag_valid; /* 0xb8 */ + u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */ + /* + * 0xbc - [31:0]: idle timeout in ms + */ + /* ACS flags */ + u32 hi_acs_flags; /* 0xc0 */ + u32 hi_console_flags; /* 0xc4 */ + u32 hi_nvram_state; /* 0xc8 */ + u32 hi_option_flag2; /* 0xcc */ + + /* If non-zero, override values sent to Host in WMI_READY event. */ + u32 hi_sw_version_override; /* 0xd0 */ + u32 hi_abi_version_override; /* 0xd4 */ + + /* + * Percentage of high priority RX traffic to total expected RX traffic - + * applicable only to ar6004 + */ + u32 hi_hp_rx_traffic_ratio; /* 0xd8 */ + + /* test applications flags */ + u32 hi_test_apps_related ; /* 0xdc */ + /* location of test script */ + u32 hi_ota_testscript; /* 0xe0 */ + /* location of CAL data */ + u32 hi_cal_data; /* 0xe4 */ + /* Number of packet log buffers */ + u32 hi_pktlog_num_buffers; /* 0xe8 */ + +} POSTPACK; + +/* Bits defined in hi_option_flag */ +#define HI_OPTION_TIMER_WAR 0x01 /* Enable timer workaround */ +#define HI_OPTION_BMI_CRED_LIMIT 0x02 /* Limit BMI command credits */ +#define HI_OPTION_RELAY_DOT11_HDR 0x04 /* Relay Dot11 hdr to/from host */ +/* MAC addr method 0-locally administred 1-globally unique addrs */ +#define HI_OPTION_MAC_ADDR_METHOD 0x08 +#define HI_OPTION_FW_BRIDGE 0x10 /* Firmware Bridging */ +#define HI_OPTION_ENABLE_PROFILE 0x20 /* Enable CPU profiling */ +#define HI_OPTION_DISABLE_DBGLOG 0x40 /* Disable debug logging */ +#define HI_OPTION_SKIP_ERA_TRACKING 0x80 /* Skip Era Tracking */ +#define HI_OPTION_PAPRD_DISABLE 0x100 /* Disable PAPRD (debug) */ +#define HI_OPTION_NUM_DEV_LSB 0x200 +#define HI_OPTION_NUM_DEV_MSB 0x800 +#define HI_OPTION_DEV_MODE_LSB 0x1000 +#define HI_OPTION_DEV_MODE_MSB 0x8000000 +/* Disable LowFreq Timer Stabilization */ +#define HI_OPTION_NO_LFT_STBL 0x10000000 +#define HI_OPTION_SKIP_REG_SCAN 0x20000000 /* Skip regulatory scan */ +/* Do regulatory scan during init beforesending WMI ready event to host */ +#define HI_OPTION_INIT_REG_SCAN 0x40000000 +#define HI_OPTION_SKIP_MEMMAP 0x80000000 /* REV6: Do not adjust memory + map */ + +/* hi_option_flag2 options */ +#define HI_OPTION_OFFLOAD_AMSDU 0x01 +#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */ + +#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3 + +/* 2 bits of hi_option_flag are used to represent 3 modes */ +#define HI_OPTION_FW_MODE_IBSS 0x0 /* IBSS Mode */ +#define HI_OPTION_FW_MODE_BSS_STA 0x1 /* STA Mode */ +#define HI_OPTION_FW_MODE_AP 0x2 /* AP Mode */ + +/* 2 bits of hi_option flag are usedto represent 4 submodes */ +#define HI_OPTION_FW_SUBMODE_NONE 0x0 /* Normal mode */ +#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 /* p2p device mode */ +#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 /* p2p client mode */ +#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 /* p2p go mode */ + +/* Num dev Mask */ +#define HI_OPTION_NUM_DEV_MASK 0x7 +#define HI_OPTION_NUM_DEV_SHIFT 0x9 + +/* firmware bridging */ +#define HI_OPTION_FW_BRIDGE_SHIFT 0x04 + +/* Fw Mode/SubMode Mask +|------------------------------------------------------------------------------| +| SUB | SUB | SUB | SUB | | | | +| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0| +| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) +|------------------------------------------------------------------------------| +*/ +#define HI_OPTION_FW_MODE_BITS 0x2 +#define HI_OPTION_FW_MODE_MASK 0x3 +#define HI_OPTION_FW_MODE_SHIFT 0xC +#define HI_OPTION_ALL_FW_MODE_MASK 0xFF + +#define HI_OPTION_FW_SUBMODE_BITS 0x2 +#define HI_OPTION_FW_SUBMODE_MASK 0x3 +#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 +#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 +#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 + +/* hi_reset_flag */ + +/* preserve App Start address */ +#define HI_RESET_FLAG_PRESERVE_APP_START 0x01 +/* preserve host interest */ +#define HI_RESET_FLAG_PRESERVE_HOST_INTEREST 0x02 +#define HI_RESET_FLAG_PRESERVE_ROMDATA 0x04 /* preserve ROM data */ +#define HI_RESET_FLAG_PRESERVE_NVRAM_STATE 0x08 +#define HI_RESET_FLAG_PRESERVE_BOOT_INFO 0x10 + +#define HI_RESET_FLAG_IS_VALID 0x12345678 /* indicate the reset flag is +valid */ + +#define ON_RESET_FLAGS_VALID() \ + (HOST_INTEREST->hi_reset_flag_valid == HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_VALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_INVALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = 0) + +#define ON_RESET_PRESERVE_APP_START() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_APP_START) + +#define ON_RESET_PRESERVE_NVRAM_STATE() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_NVRAM_STATE) + +#define ON_RESET_PRESERVE_HOST_INTEREST() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_HOST_INTEREST) + +#define ON_RESET_PRESERVE_ROMDATA() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_ROMDATA) + +#define ON_RESET_PRESERVE_BOOT_INFO() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_BOOT_INFO) + +#define HI_ACS_FLAGS_ENABLED (1 << 0) /* ACS is enabled */ +#define HI_ACS_FLAGS_USE_WWAN (1 << 1) /* Use physical WWAN device */ +#define HI_ACS_FLAGS_TEST_VAP (1 << 2) /* Use test VAP */ + +/* CONSOLE FLAGS + * + * Bit Range Meaning + * --------- -------------------------------- + * 2..0 UART ID (0 = Default) + * 3 Baud Select (0 = 9600, 1 = 115200) + * 30..4 Reserved + * 31 Enable Console + * + */ + +#define HI_CONSOLE_FLAGS_ENABLE (1 << 31) +#define HI_CONSOLE_FLAGS_UART_MASK (0x7) +#define HI_CONSOLE_FLAGS_UART_SHIFT 0 +#define HI_CONSOLE_FLAGS_BAUD_SELECT (1 << 3) + +/* + * Intended for use by Host software, this macro returns the Target RAM + * address of any item in the host_interest structure. + * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data); + */ +#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \ + (u32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item))) + +#define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \ + (u32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item))) + +#define AR6004_HOST_INTEREST_ITEM_ADDRESS(item) \ + ((u32)&((((struct host_interest_s *)(AR6004_HOST_INTEREST_ADDRESS))->item))) + + +#define HOST_INTEREST_DBGLOG_IS_ENABLED() \ + (!(HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG)) + +#define HOST_INTEREST_PKTLOG_IS_ENABLED() \ + ((HOST_INTEREST->hi_pktlog_num_buffers)) + + +#define HOST_INTEREST_PROFILE_IS_ENABLED() \ + (HOST_INTEREST->hi_option_flag & HI_OPTION_ENABLE_PROFILE) + +#define LF_TIMER_STABILIZATION_IS_ENABLED() \ + (!(HOST_INTEREST->hi_option_flag & HI_OPTION_NO_LFT_STBL)) + +#define IS_AMSDU_OFFLAOD_ENABLED() \ + ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_OFFLOAD_AMSDU)) + +#define HOST_INTEREST_DFS_IS_ENABLED() \ + ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_DFS_SUPPORT)) + +/* Convert a Target virtual address into a Target physical address */ +#define AR6002_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define TARG_VTOP(TargetType, vaddr) \ + (((TargetType) == TARGET_TYPE_AR6002) ? AR6002_VTOP(vaddr) : AR6003_VTOP(vaddr)) + +#define AR6003_REV2_APP_START_OVERRIDE 0x944C00 +#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 +#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 +#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 +#define AR6003_REV2_RAM_RESERVE_SIZE 6912 + +#define AR6003_REV3_APP_START_OVERRIDE 0x945d00 +#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 +#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 +#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 +#define AR6003_REV3_RAM_RESERVE_SIZE 512 + +#define AR6003_BOARD_EXT_DATA_ADDRESS 0x57E600 + +/* # of u32 entries in targregs, used by DIAG_FETCH_TARG_REGS */ +#define AR6003_FETCH_TARG_REGS_COUNT 64 + +#endif /* !__ASSEMBLER__ */ + +#endif /* __TARGADDRS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/testcmd.h b/trunk/drivers/staging/ath6kl/include/common/testcmd.h new file mode 100644 index 000000000000..7d94aee508b3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/testcmd.h @@ -0,0 +1,185 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef TESTCMD_H_ +#define TESTCMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef AR6002_REV2 +#define TCMD_MAX_RATES 12 +#else +#define TCMD_MAX_RATES 28 +#endif + +typedef enum { + ZEROES_PATTERN = 0, + ONES_PATTERN, + REPEATING_10, + PN7_PATTERN, + PN9_PATTERN, + PN15_PATTERN +}TX_DATA_PATTERN; + +/* Continuous tx + mode : TCMD_CONT_TX_OFF - Disabling continuous tx + TCMD_CONT_TX_SINE - Enable continuous unmodulated tx + TCMD_CONT_TX_FRAME- Enable continuous modulated tx + freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g) +dataRate: 0 - 1 Mbps + 1 - 2 Mbps + 2 - 5.5 Mbps + 3 - 11 Mbps + 4 - 6 Mbps + 5 - 9 Mbps + 6 - 12 Mbps + 7 - 18 Mbps + 8 - 24 Mbps + 9 - 36 Mbps + 10 - 28 Mbps + 11 - 54 Mbps + txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx +antenna: 1 - one antenna + 2 - two antenna +Note : Enable/disable continuous tx test cmd works only when target is awake. +*/ + +typedef enum { + TCMD_CONT_TX_OFF = 0, + TCMD_CONT_TX_SINE, + TCMD_CONT_TX_FRAME, + TCMD_CONT_TX_TX99, + TCMD_CONT_TX_TX100 +} TCMD_CONT_TX_MODE; + +typedef enum { + TCMD_WLAN_MODE_NOHT = 0, + TCMD_WLAN_MODE_HT20 = 1, + TCMD_WLAN_MODE_HT40PLUS = 2, + TCMD_WLAN_MODE_HT40MINUS = 3, +} TCMD_WLAN_MODE; + +typedef PREPACK struct { + u32 testCmdId; + u32 mode; + u32 freq; + u32 dataRate; + s32 txPwr; + u32 antenna; + u32 enANI; + u32 scramblerOff; + u32 aifsn; + u16 pktSz; + u16 txPattern; + u32 shortGuard; + u32 numPackets; + u32 wlanMode; +} POSTPACK TCMD_CONT_TX; + +#define TCMD_TXPATTERN_ZERONE 0x1 +#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2 + +/* Continuous Rx + act: TCMD_CONT_RX_PROMIS - promiscuous mode (accept all incoming frames) + TCMD_CONT_RX_FILTER - filter mode (accept only frames with dest + address equal specified + mac address (set via act =3) + TCMD_CONT_RX_REPORT off mode (disable cont rx mode and get the + report from the last cont + Rx test) + + TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the + target. This Overrides + the default MAC address.) + +*/ +typedef enum { + TCMD_CONT_RX_PROMIS =0, + TCMD_CONT_RX_FILTER, + TCMD_CONT_RX_REPORT, + TCMD_CONT_RX_SETMAC, + TCMD_CONT_RX_SET_ANT_SWITCH_TABLE +} TCMD_CONT_RX_ACT; + +typedef PREPACK struct { + u32 testCmdId; + u32 act; + u32 enANI; + PREPACK union { + struct PREPACK TCMD_CONT_RX_PARA { + u32 freq; + u32 antenna; + u32 wlanMode; + } POSTPACK para; + struct PREPACK TCMD_CONT_RX_REPORT { + u32 totalPkt; + s32 rssiInDBm; + u32 crcErrPkt; + u32 secErrPkt; + u16 rateCnt[TCMD_MAX_RATES]; + u16 rateCntShortGuard[TCMD_MAX_RATES]; + } POSTPACK report; + struct PREPACK TCMD_CONT_RX_MAC { + u8 addr[ATH_MAC_LEN]; + } POSTPACK mac; + struct PREPACK TCMD_CONT_RX_ANT_SWITCH_TABLE { + u32 antswitch1; + u32 antswitch2; + }POSTPACK antswitchtable; + } POSTPACK u; +} POSTPACK TCMD_CONT_RX; + +/* Force sleep/wake test cmd + mode: TCMD_PM_WAKEUP - Wakeup the target + TCMD_PM_SLEEP - Force the target to sleep. + */ +typedef enum { + TCMD_PM_WAKEUP = 1, /* be consistent with target */ + TCMD_PM_SLEEP, + TCMD_PM_DEEPSLEEP +} TCMD_PM_MODE; + +typedef PREPACK struct { + u32 testCmdId; + u32 mode; +} POSTPACK TCMD_PM; + +typedef enum { + TCMD_CONT_TX_ID, + TCMD_CONT_RX_ID, + TCMD_PM_ID +} TCMD_ID; + +typedef PREPACK union { + TCMD_CONT_TX contTx; + TCMD_CONT_RX contRx; + TCMD_PM pm; +} POSTPACK TEST_CMD; + +#ifdef __cplusplus +} +#endif + +#endif /* TESTCMD_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/tlpm.h b/trunk/drivers/staging/ath6kl/include/common/tlpm.h new file mode 100644 index 000000000000..659b1c07ba90 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/tlpm.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __TLPM_H__ +#define __TLPM_H__ + +/* idle timeout in 16-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */ +#define TLPM_DEFAULT_IDLE_TIMEOUT_MS 1000 +/* hex in LSB and MSB for HCI command */ +#define TLPM_DEFAULT_IDLE_TIMEOUT_LSB 0xE8 +#define TLPM_DEFAULT_IDLE_TIMEOUT_MSB 0x3 + +/* wakeup timeout in 8-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */ +#define TLPM_DEFAULT_WAKEUP_TIMEOUT_MS 10 + +/* default UART FC polarity is low */ +#define TLPM_DEFAULT_UART_FC_POLARITY 0 + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h b/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h new file mode 100644 index 000000000000..03e4d23788ce --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h @@ -0,0 +1,79 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef __WLAN_DEFS_H__ +#define __WLAN_DEFS_H__ + +/* + * This file contains WLAN definitions that may be used across both + * Host and Target software. + */ + +typedef enum { + MODE_11A = 0, /* 11a Mode */ + MODE_11G = 1, /* 11b/g Mode */ + MODE_11B = 2, /* 11b Mode */ + MODE_11GONLY = 3, /* 11g only Mode */ +#ifdef SUPPORT_11N + MODE_11NA_HT20 = 4, /* 11a HT20 mode */ + MODE_11NG_HT20 = 5, /* 11g HT20 mode */ + MODE_11NA_HT40 = 6, /* 11a HT40 mode */ + MODE_11NG_HT40 = 7, /* 11g HT40 mode */ + MODE_UNKNOWN = 8, + MODE_MAX = 8 +#else + MODE_UNKNOWN = 4, + MODE_MAX = 4 +#endif +} WLAN_PHY_MODE; + +typedef enum { + WLAN_11A_CAPABILITY = 1, + WLAN_11G_CAPABILITY = 2, + WLAN_11AG_CAPABILITY = 3, +}WLAN_CAPABILITY; + +#ifdef SUPPORT_11N +typedef unsigned long A_RATEMASK; +#else +typedef unsigned short A_RATEMASK; +#endif + +#ifdef SUPPORT_11N +#define IS_MODE_11A(mode) (((mode) == MODE_11A) || \ + ((mode) == MODE_11NA_HT20) || \ + ((mode) == MODE_11NA_HT40)) +#define IS_MODE_11B(mode) ((mode) == MODE_11B) +#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \ + ((mode) == MODE_11GONLY) || \ + ((mode) == MODE_11NG_HT20) || \ + ((mode) == MODE_11NG_HT40)) +#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY) +#else +#define IS_MODE_11A(mode) ((mode) == MODE_11A) +#define IS_MODE_11B(mode) ((mode) == MODE_11B) +#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \ + ((mode) == MODE_11GONLY)) +#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY) +#endif /* SUPPORT_11N */ + +#endif /* __WLANDEFS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/wmi.h b/trunk/drivers/staging/ath6kl/include/common/wmi.h new file mode 100644 index 000000000000..d9687443d32c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wmi.h @@ -0,0 +1,3220 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +/* + * This file contains the definitions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all the + * commands and events. Commands are messages from the host to the WM. + * Events and Replies are messages from the WM to the host. + * + * Ownership of correctness in regards to commands + * belongs to the host driver and the WMI is not required to validate + * parameters for value, proper range, or any other checking. + * + */ + +#ifndef _WMI_H_ +#define _WMI_H_ + +#include "wmix.h" +#include "wlan_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HTC_PROTOCOL_VERSION 0x0002 +#define HTC_PROTOCOL_REVISION 0x0000 + +#define WMI_PROTOCOL_VERSION 0x0002 +#define WMI_PROTOCOL_REVISION 0x0000 + +#define ATH_MAC_LEN 6 /* length of mac in bytes */ +#define WMI_CMD_MAX_LEN 100 +#define WMI_CONTROL_MSG_MAX_LEN 256 +#define WMI_OPT_CONTROL_MSG_MAX_LEN 1536 +#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600) +#define RFC1042OUI {0x00, 0x00, 0x00} + +#define IP_ETHERTYPE 0x0800 + +#define WMI_IMPLICIT_PSTREAM 0xFF +#define WMI_MAX_THINSTREAM 15 + +#ifdef AR6002_REV2 +#define IBSS_MAX_NUM_STA 4 +#else +#define IBSS_MAX_NUM_STA 8 +#endif + +PREPACK struct host_app_area_s { + u32 wmi_protocol_ver; +} POSTPACK; + +/* + * Data Path + */ +typedef PREPACK struct { + u8 dstMac[ATH_MAC_LEN]; + u8 srcMac[ATH_MAC_LEN]; + u16 typeOrLen; +} POSTPACK ATH_MAC_HDR; + +typedef PREPACK struct { + u8 dsap; + u8 ssap; + u8 cntl; + u8 orgCode[3]; + u16 etherType; +} POSTPACK ATH_LLC_SNAP_HDR; + +typedef enum { + DATA_MSGTYPE = 0x0, + CNTL_MSGTYPE, + SYNC_MSGTYPE, + OPT_MSGTYPE, +} WMI_MSG_TYPE; + + +/* + * Macros for operating on WMI_DATA_HDR (info) field + */ + +#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03 +#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0 +#define WMI_DATA_HDR_UP_MASK 0x07 +#define WMI_DATA_HDR_UP_SHIFT 2 +/* In AP mode, the same bit (b5) is used to indicate Power save state in + * the Rx dir and More data bit state in the tx direction. + */ +#define WMI_DATA_HDR_PS_MASK 0x1 +#define WMI_DATA_HDR_PS_SHIFT 5 + +#define WMI_DATA_HDR_MORE_MASK 0x1 +#define WMI_DATA_HDR_MORE_SHIFT 5 + +typedef enum { + WMI_DATA_HDR_DATA_TYPE_802_3 = 0, + WMI_DATA_HDR_DATA_TYPE_802_11, + WMI_DATA_HDR_DATA_TYPE_ACL, /* used to be used for the PAL */ +} WMI_DATA_HDR_DATA_TYPE; + +#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 +#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 + +#define WMI_DATA_HDR_SET_MORE_BIT(h) ((h)->info |= (WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT)) + +#define WMI_DATA_HDR_IS_MSG_TYPE(h, t) (((h)->info & (WMI_DATA_HDR_MSG_TYPE_MASK)) == (t)) +#define WMI_DATA_HDR_SET_MSG_TYPE(h, t) (h)->info = (((h)->info & ~(WMI_DATA_HDR_MSG_TYPE_MASK << WMI_DATA_HDR_MSG_TYPE_SHIFT)) | (t << WMI_DATA_HDR_MSG_TYPE_SHIFT)) +#define WMI_DATA_HDR_GET_UP(h) (((h)->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK) +#define WMI_DATA_HDR_SET_UP(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT)) | (p << WMI_DATA_HDR_UP_SHIFT)) + +#define WMI_DATA_HDR_GET_DATA_TYPE(h) (((h)->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) & WMI_DATA_HDR_DATA_TYPE_MASK) +#define WMI_DATA_HDR_SET_DATA_TYPE(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_DATA_TYPE_MASK << WMI_DATA_HDR_DATA_TYPE_SHIFT)) | ((p) << WMI_DATA_HDR_DATA_TYPE_SHIFT)) + +#define WMI_DATA_HDR_GET_DOT11(h) (WMI_DATA_HDR_GET_DATA_TYPE((h)) == WMI_DATA_HDR_DATA_TYPE_802_11) +#define WMI_DATA_HDR_SET_DOT11(h, p) WMI_DATA_HDR_SET_DATA_TYPE((h), (p)) + +/* Macros for operating on WMI_DATA_HDR (info2) field */ +#define WMI_DATA_HDR_SEQNO_MASK 0xFFF +#define WMI_DATA_HDR_SEQNO_SHIFT 0 + +#define WMI_DATA_HDR_AMSDU_MASK 0x1 +#define WMI_DATA_HDR_AMSDU_SHIFT 12 + +#define WMI_DATA_HDR_META_MASK 0x7 +#define WMI_DATA_HDR_META_SHIFT 13 + +#define GET_SEQ_NO(_v) ((_v) & WMI_DATA_HDR_SEQNO_MASK) +#define GET_ISMSDU(_v) ((_v) & WMI_DATA_HDR_AMSDU_MASK) + +#define WMI_DATA_HDR_GET_SEQNO(h) GET_SEQ_NO((h)->info2 >> WMI_DATA_HDR_SEQNO_SHIFT) +#define WMI_DATA_HDR_SET_SEQNO(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_SEQNO_MASK << WMI_DATA_HDR_SEQNO_SHIFT)) | (GET_SEQ_NO(_v) << WMI_DATA_HDR_SEQNO_SHIFT)) + +#define WMI_DATA_HDR_IS_AMSDU(h) GET_ISMSDU((h)->info2 >> WMI_DATA_HDR_AMSDU_SHIFT) +#define WMI_DATA_HDR_SET_AMSDU(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_AMSDU_MASK << WMI_DATA_HDR_AMSDU_SHIFT)) | (GET_ISMSDU(_v) << WMI_DATA_HDR_AMSDU_SHIFT)) + +#define WMI_DATA_HDR_GET_META(h) (((h)->info2 >> WMI_DATA_HDR_META_SHIFT) & WMI_DATA_HDR_META_MASK) +#define WMI_DATA_HDR_SET_META(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_META_MASK << WMI_DATA_HDR_META_SHIFT)) | ((_v) << WMI_DATA_HDR_META_SHIFT)) + +/* Macros for operating on WMI_DATA_HDR (info3) field */ +#define WMI_DATA_HDR_DEVID_MASK 0xF +#define WMI_DATA_HDR_DEVID_SHIFT 0 +#define GET_DEVID(_v) ((_v) & WMI_DATA_HDR_DEVID_MASK) + +#define WMI_DATA_HDR_GET_DEVID(h) \ + (((h)->info3 >> WMI_DATA_HDR_DEVID_SHIFT) & WMI_DATA_HDR_DEVID_MASK) +#define WMI_DATA_HDR_SET_DEVID(h, _v) \ + ((h)->info3 = ((h)->info3 & ~(WMI_DATA_HDR_DEVID_MASK << WMI_DATA_HDR_DEVID_SHIFT)) | (GET_DEVID(_v) << WMI_DATA_HDR_DEVID_SHIFT)) + +typedef PREPACK struct { + s8 rssi; + u8 info; /* usage of 'info' field(8-bit): + * b1:b0 - WMI_MSG_TYPE + * b4:b3:b2 - UP(tid) + * b5 - Used in AP mode. More-data in tx dir, PS in rx. + * b7:b6 - Dot3 header(0), + * Dot11 Header(1), + * ACL data(2) + */ + + u16 info2; /* usage of 'info2' field(16-bit): + * b11:b0 - seq_no + * b12 - A-MSDU? + * b15:b13 - META_DATA_VERSION 0 - 7 + */ + u16 info3; +} POSTPACK WMI_DATA_HDR; + +/* + * TX META VERSION DEFINITIONS + */ +#define WMI_MAX_TX_META_SZ (12) +#define WMI_MAX_TX_META_VERSION (7) +#define WMI_META_VERSION_1 (0x01) +#define WMI_META_VERSION_2 (0X02) + +#define WMI_ACL_TO_DOT11_HEADROOM 36 + +#if 0 /* removed to prevent compile errors for WM.. */ +typedef PREPACK struct { +/* intentionally empty. Default version is no meta data. */ +} POSTPACK WMI_TX_META_V0; +#endif + +typedef PREPACK struct { + u8 pktID; /* The packet ID to identify the tx request */ + u8 ratePolicyID; /* The rate policy to be used for the tx of this frame */ +} POSTPACK WMI_TX_META_V1; + + +#define WMI_CSUM_DIR_TX (0x1) +#define TX_CSUM_CALC_FILL (0x1) +typedef PREPACK struct { + u8 csumStart; /*Offset from start of the WMI header for csum calculation to begin */ + u8 csumDest; /*Offset from start of WMI header where final csum goes*/ + u8 csumFlags; /*number of bytes over which csum is calculated*/ +} POSTPACK WMI_TX_META_V2; + + +/* + * RX META VERSION DEFINITIONS + */ +/* if RX meta data is present at all then the meta data field + * will consume WMI_MAX_RX_META_SZ bytes of space between the + * WMI_DATA_HDR and the payload. How much of the available + * Meta data is actually used depends on which meta data + * version is active. */ +#define WMI_MAX_RX_META_SZ (12) +#define WMI_MAX_RX_META_VERSION (7) + +#define WMI_RX_STATUS_OK 0 /* success */ +#define WMI_RX_STATUS_DECRYPT_ERR 1 /* decrypt error */ +#define WMI_RX_STATUS_MIC_ERR 2 /* tkip MIC error */ +#define WMI_RX_STATUS_ERR 3 /* undefined error */ + +#define WMI_RX_FLAGS_AGGR 0x0001 /* part of AGGR */ +#define WMI_RX_FlAGS_STBC 0x0002 /* used STBC */ +#define WMI_RX_FLAGS_SGI 0x0004 /* used SGI */ +#define WMI_RX_FLAGS_HT 0x0008 /* is HT packet */ +/* the flags field is also used to store the CRYPTO_TYPE of the frame + * that value is shifted by WMI_RX_FLAGS_CRYPTO_SHIFT */ +#define WMI_RX_FLAGS_CRYPTO_SHIFT 4 +#define WMI_RX_FLAGS_CRYPTO_MASK 0x1f +#define WMI_RX_META_GET_CRYPTO(flags) (((flags) >> WMI_RX_FLAGS_CRYPTO_SHIFT) & WMI_RX_FLAGS_CRYPTO_MASK) + +#if 0 /* removed to prevent compile errors for WM.. */ +typedef PREPACK struct { +/* intentionally empty. Default version is no meta data. */ +} POSTPACK WMI_RX_META_VERSION_0; +#endif + +typedef PREPACK struct { + u8 status; /* one of WMI_RX_STATUS_... */ + u8 rix; /* rate index mapped to rate at which this packet was received. */ + u8 rssi; /* rssi of packet */ + u8 channel;/* rf channel during packet reception */ + u16 flags; /* a combination of WMI_RX_FLAGS_... */ +} POSTPACK WMI_RX_META_V1; + +#define RX_CSUM_VALID_FLAG (0x1) +typedef PREPACK struct { + u16 csum; + u8 csumFlags;/* bit 0 set -partial csum valid + bit 1 set -test mode */ +} POSTPACK WMI_RX_META_V2; + + + +#define WMI_GET_DEVICE_ID(info1) ((info1) & 0xF) +/* Macros for operating on WMI_CMD_HDR (info1) field */ +#define WMI_CMD_HDR_DEVID_MASK 0xF +#define WMI_CMD_HDR_DEVID_SHIFT 0 +#define GET_CMD_DEVID(_v) ((_v) & WMI_CMD_HDR_DEVID_MASK) + +#define WMI_CMD_HDR_GET_DEVID(h) \ + (((h)->info1 >> WMI_CMD_HDR_DEVID_SHIFT) & WMI_CMD_HDR_DEVID_MASK) +#define WMI_CMD_HDR_SET_DEVID(h, _v) \ + ((h)->info1 = ((h)->info1 & \ + ~(WMI_CMD_HDR_DEVID_MASK << WMI_CMD_HDR_DEVID_SHIFT)) | \ + (GET_CMD_DEVID(_v) << WMI_CMD_HDR_DEVID_SHIFT)) + +/* + * Control Path + */ +typedef PREPACK struct { + u16 commandId; +/* + * info1 - 16 bits + * b03:b00 - id + * b15:b04 - unused + */ + u16 info1; + + u16 reserved; /* For alignment */ +} POSTPACK WMI_CMD_HDR; /* used for commands and events */ + +/* + * List of Commnands + */ +typedef enum { + WMI_CONNECT_CMDID = 0x0001, + WMI_RECONNECT_CMDID, + WMI_DISCONNECT_CMDID, + WMI_SYNCHRONIZE_CMDID, + WMI_CREATE_PSTREAM_CMDID, + WMI_DELETE_PSTREAM_CMDID, + WMI_START_SCAN_CMDID, + WMI_SET_SCAN_PARAMS_CMDID, + WMI_SET_BSS_FILTER_CMDID, + WMI_SET_PROBED_SSID_CMDID, /* 10 */ + WMI_SET_LISTEN_INT_CMDID, + WMI_SET_BMISS_TIME_CMDID, + WMI_SET_DISC_TIMEOUT_CMDID, + WMI_GET_CHANNEL_LIST_CMDID, + WMI_SET_BEACON_INT_CMDID, + WMI_GET_STATISTICS_CMDID, + WMI_SET_CHANNEL_PARAMS_CMDID, + WMI_SET_POWER_MODE_CMDID, + WMI_SET_IBSS_PM_CAPS_CMDID, + WMI_SET_POWER_PARAMS_CMDID, /* 20 */ + WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + WMI_ADD_CIPHER_KEY_CMDID, + WMI_DELETE_CIPHER_KEY_CMDID, + WMI_ADD_KRK_CMDID, + WMI_DELETE_KRK_CMDID, + WMI_SET_PMKID_CMDID, + WMI_SET_TX_PWR_CMDID, + WMI_GET_TX_PWR_CMDID, + WMI_SET_ASSOC_INFO_CMDID, + WMI_ADD_BAD_AP_CMDID, /* 30 */ + WMI_DELETE_BAD_AP_CMDID, + WMI_SET_TKIP_COUNTERMEASURES_CMDID, + WMI_RSSI_THRESHOLD_PARAMS_CMDID, + WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + WMI_SET_ACCESS_PARAMS_CMDID, + WMI_SET_RETRY_LIMITS_CMDID, + WMI_SET_OPT_MODE_CMDID, + WMI_OPT_TX_FRAME_CMDID, + WMI_SET_VOICE_PKT_SIZE_CMDID, + WMI_SET_MAX_SP_LEN_CMDID, /* 40 */ + WMI_SET_ROAM_CTRL_CMDID, + WMI_GET_ROAM_TBL_CMDID, + WMI_GET_ROAM_DATA_CMDID, + WMI_ENABLE_RM_CMDID, + WMI_SET_MAX_OFFHOME_DURATION_CMDID, + WMI_EXTENSION_CMDID, /* Non-wireless extensions */ + WMI_SNR_THRESHOLD_PARAMS_CMDID, + WMI_LQ_THRESHOLD_PARAMS_CMDID, + WMI_SET_LPREAMBLE_CMDID, + WMI_SET_RTS_CMDID, /* 50 */ + WMI_CLR_RSSI_SNR_CMDID, + WMI_SET_FIXRATES_CMDID, + WMI_GET_FIXRATES_CMDID, + WMI_SET_AUTH_MODE_CMDID, + WMI_SET_REASSOC_MODE_CMDID, + WMI_SET_WMM_CMDID, + WMI_SET_WMM_TXOP_CMDID, + WMI_TEST_CMDID, + /* COEX AR6002 only*/ + WMI_SET_BT_STATUS_CMDID, + WMI_SET_BT_PARAMS_CMDID, /* 60 */ + + WMI_SET_KEEPALIVE_CMDID, + WMI_GET_KEEPALIVE_CMDID, + WMI_SET_APPIE_CMDID, + WMI_GET_APPIE_CMDID, + WMI_SET_WSC_STATUS_CMDID, + + /* Wake on Wireless */ + WMI_SET_HOST_SLEEP_MODE_CMDID, + WMI_SET_WOW_MODE_CMDID, + WMI_GET_WOW_LIST_CMDID, + WMI_ADD_WOW_PATTERN_CMDID, + WMI_DEL_WOW_PATTERN_CMDID, /* 70 */ + + WMI_SET_FRAMERATES_CMDID, + WMI_SET_AP_PS_CMDID, + WMI_SET_QOS_SUPP_CMDID, + /* WMI_THIN_RESERVED_... mark the start and end + * values for WMI_THIN_RESERVED command IDs. These + * command IDs can be found in wmi_thin.h */ + WMI_THIN_RESERVED_START = 0x8000, + WMI_THIN_RESERVED_END = 0x8fff, + /* + * Developer commands starts at 0xF000 + */ + WMI_SET_BITRATE_CMDID = 0xF000, + WMI_GET_BITRATE_CMDID, + WMI_SET_WHALPARAM_CMDID, + + + /*Should add the new command to the tail for compatible with + * etna. + */ + WMI_SET_MAC_ADDRESS_CMDID, + WMI_SET_AKMP_PARAMS_CMDID, + WMI_SET_PMKID_LIST_CMDID, + WMI_GET_PMKID_LIST_CMDID, + WMI_ABORT_SCAN_CMDID, + WMI_SET_TARGET_EVENT_REPORT_CMDID, + + // Unused + WMI_UNUSED1, + WMI_UNUSED2, + + /* + * AP mode commands + */ + WMI_AP_HIDDEN_SSID_CMDID, + WMI_AP_SET_NUM_STA_CMDID, + WMI_AP_ACL_POLICY_CMDID, + WMI_AP_ACL_MAC_LIST_CMDID, + WMI_AP_CONFIG_COMMIT_CMDID, + WMI_AP_SET_MLME_CMDID, + WMI_AP_SET_PVB_CMDID, + WMI_AP_CONN_INACT_CMDID, + WMI_AP_PROT_SCAN_TIME_CMDID, + WMI_AP_SET_COUNTRY_CMDID, + WMI_AP_SET_DTIM_CMDID, + WMI_AP_MODE_STAT_CMDID, + + WMI_SET_IP_CMDID, + WMI_SET_PARAMS_CMDID, + WMI_SET_MCAST_FILTER_CMDID, + WMI_DEL_MCAST_FILTER_CMDID, + + WMI_ALLOW_AGGR_CMDID, + WMI_ADDBA_REQ_CMDID, + WMI_DELBA_REQ_CMDID, + WMI_SET_HT_CAP_CMDID, + WMI_SET_HT_OP_CMDID, + WMI_SET_TX_SELECT_RATES_CMDID, + WMI_SET_TX_SGI_PARAM_CMDID, + WMI_SET_RATE_POLICY_CMDID, + + WMI_HCI_CMD_CMDID, + WMI_RX_FRAME_FORMAT_CMDID, + WMI_SET_THIN_MODE_CMDID, + WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, + + WMI_AP_SET_11BG_RATESET_CMDID, + WMI_SET_PMK_CMDID, + WMI_MCAST_FILTER_CMDID, + /* COEX CMDID AR6003*/ + WMI_SET_BTCOEX_FE_ANT_CMDID, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, + WMI_SET_BTCOEX_SCO_CONFIG_CMDID, + WMI_SET_BTCOEX_A2DP_CONFIG_CMDID, + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, + WMI_SET_BTCOEX_DEBUG_CMDID, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID, + WMI_GET_BTCOEX_STATS_CMDID, + WMI_GET_BTCOEX_CONFIG_CMDID, + + WMI_SET_DFS_ENABLE_CMDID, /* F034 */ + WMI_SET_DFS_MINRSSITHRESH_CMDID, + WMI_SET_DFS_MAXPULSEDUR_CMDID, + WMI_DFS_RADAR_DETECTED_CMDID, + + /* P2P CMDS */ + WMI_P2P_SET_CONFIG_CMDID, /* F038 */ + WMI_WPS_SET_CONFIG_CMDID, + WMI_SET_REQ_DEV_ATTR_CMDID, + WMI_P2P_FIND_CMDID, + WMI_P2P_STOP_FIND_CMDID, + WMI_P2P_GO_NEG_START_CMDID, + WMI_P2P_LISTEN_CMDID, + + WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */ + WMI_SET_PROMISCUOUS_MODE_CMDID, + WMI_RX_FRAME_FILTER_CMDID, + WMI_SET_CHANNEL_CMDID, + + /* WAC commands */ + WMI_ENABLE_WAC_CMDID, + WMI_WAC_SCAN_REPLY_CMDID, + WMI_WAC_CTRL_REQ_CMDID, + WMI_SET_DIV_PARAMS_CMDID, + + WMI_GET_PMK_CMDID, + WMI_SET_PASSPHRASE_CMDID, + WMI_SEND_ASSOC_RES_CMDID, + WMI_SET_ASSOC_REQ_RELAY_CMDID, + WMI_GET_RFKILL_MODE_CMDID, + + /* ACS command, consists of sub-commands */ + WMI_ACS_CTRL_CMDID, + + /* Ultra low power store / recall commands */ + WMI_STORERECALL_CONFIGURE_CMDID, + WMI_STORERECALL_RECALL_CMDID, + WMI_STORERECALL_HOST_READY_CMDID, + WMI_FORCE_TARGET_ASSERT_CMDID, + WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, +} WMI_COMMAND_ID; + +/* + * Frame Types + */ +typedef enum { + WMI_FRAME_BEACON = 0, + WMI_FRAME_PROBE_REQ, + WMI_FRAME_PROBE_RESP, + WMI_FRAME_ASSOC_REQ, + WMI_FRAME_ASSOC_RESP, + WMI_NUM_MGMT_FRAME +} WMI_MGMT_FRAME_TYPE; + +/* + * Connect Command + */ +typedef enum { + INFRA_NETWORK = 0x01, + ADHOC_NETWORK = 0x02, + ADHOC_CREATOR = 0x04, + AP_NETWORK = 0x10, +} NETWORK_TYPE; + +typedef enum { + OPEN_AUTH = 0x01, + SHARED_AUTH = 0x02, + LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */ +} DOT11_AUTH_MODE; + +enum { + AUTH_IDLE, + AUTH_OPEN_IN_PROGRESS, +}; + +typedef enum { + NONE_AUTH = 0x01, + WPA_AUTH = 0x02, + WPA2_AUTH = 0x04, + WPA_PSK_AUTH = 0x08, + WPA2_PSK_AUTH = 0x10, + WPA_AUTH_CCKM = 0x20, + WPA2_AUTH_CCKM = 0x40, +} AUTH_MODE; + +typedef enum { + NONE_CRYPT = 0x01, + WEP_CRYPT = 0x02, + TKIP_CRYPT = 0x04, + AES_CRYPT = 0x08, +#ifdef WAPI_ENABLE + WAPI_CRYPT = 0x10, +#endif /*WAPI_ENABLE*/ +} CRYPTO_TYPE; + +#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT +#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1) + +#ifdef WAPI_ENABLE +#undef WMI_MAX_CRYPTO_TYPE +#define WMI_MAX_CRYPTO_TYPE (WAPI_CRYPT + 1) +#endif /* WAPI_ENABLE */ + +#ifdef WAPI_ENABLE +#define IW_ENCODE_ALG_SM4 0x20 +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif + +#define WMI_MIN_KEY_INDEX 0 +#define WMI_MAX_KEY_INDEX 3 + +#ifdef WAPI_ENABLE +#undef WMI_MAX_KEY_INDEX +#define WMI_MAX_KEY_INDEX 7 /* wapi grpKey 0-3, prwKey 4-7 */ +#endif /* WAPI_ENABLE */ + +#define WMI_MAX_KEY_LEN 32 + +#define WMI_MAX_SSID_LEN 32 + +typedef enum { + CONNECT_ASSOC_POLICY_USER = 0x0001, + CONNECT_SEND_REASSOC = 0x0002, + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, + CONNECT_PROFILE_MATCH_DONE = 0x0008, + CONNECT_IGNORE_AAC_BEACON = 0x0010, + CONNECT_CSA_FOLLOW_BSS = 0x0020, + CONNECT_DO_WPA_OFFLOAD = 0x0040, + CONNECT_DO_NOT_DEAUTH = 0x0080, +} WMI_CONNECT_CTRL_FLAGS_BITS; + +#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS) + +typedef PREPACK struct { + u8 networkType; + u8 dot11AuthMode; + u8 authMode; + u8 pairwiseCryptoType; + u8 pairwiseCryptoLen; + u8 groupCryptoType; + u8 groupCryptoLen; + u8 ssidLength; + u8 ssid[WMI_MAX_SSID_LEN]; + u16 channel; + u8 bssid[ATH_MAC_LEN]; + u32 ctrl_flags; +} POSTPACK WMI_CONNECT_CMD; + +/* + * WMI_RECONNECT_CMDID + */ +typedef PREPACK struct { + u16 channel; /* hint */ + u8 bssid[ATH_MAC_LEN]; /* mandatory if set */ +} POSTPACK WMI_RECONNECT_CMD; + +#define WMI_PMK_LEN 32 +typedef PREPACK struct { + u8 pmk[WMI_PMK_LEN]; +} POSTPACK WMI_SET_PMK_CMD; + +/* + * WMI_SET_EXCESS_TX_RETRY_THRES_CMDID + */ +typedef PREPACK struct { + u32 threshold; +} POSTPACK WMI_SET_EXCESS_TX_RETRY_THRES_CMD; + +/* + * WMI_ADD_CIPHER_KEY_CMDID + */ +typedef enum { + PAIRWISE_USAGE = 0x00, + GROUP_USAGE = 0x01, + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */ +} KEY_USAGE; + +/* + * Bit Flag + * Bit 0 - Initialise TSC - default is Initialize + */ +#define KEY_OP_INIT_TSC 0x01 +#define KEY_OP_INIT_RSC 0x02 +#ifdef WAPI_ENABLE +#define KEY_OP_INIT_WAPIPN 0x10 +#endif /* WAPI_ENABLE */ + +#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */ +#define KEY_OP_VALID_MASK 0x03 + +typedef PREPACK struct { + u8 keyIndex; + u8 keyType; + u8 keyUsage; /* KEY_USAGE */ + u8 keyLength; + u8 keyRSC[8]; /* key replay sequence counter */ + u8 key[WMI_MAX_KEY_LEN]; + u8 key_op_ctrl; /* Additional Key Control information */ + u8 key_macaddr[ATH_MAC_LEN]; +} POSTPACK WMI_ADD_CIPHER_KEY_CMD; + +/* + * WMI_DELETE_CIPHER_KEY_CMDID + */ +typedef PREPACK struct { + u8 keyIndex; +} POSTPACK WMI_DELETE_CIPHER_KEY_CMD; + +#define WMI_KRK_LEN 16 +/* + * WMI_ADD_KRK_CMDID + */ +typedef PREPACK struct { + u8 krk[WMI_KRK_LEN]; +} POSTPACK WMI_ADD_KRK_CMD; + +/* + * WMI_SET_TKIP_COUNTERMEASURES_CMDID + */ +typedef enum { + WMI_TKIP_CM_DISABLE = 0x0, + WMI_TKIP_CM_ENABLE = 0x1, +} WMI_TKIP_CM_CONTROL; + +typedef PREPACK struct { + u8 cm_en; /* WMI_TKIP_CM_CONTROL */ +} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD; + +/* + * WMI_SET_PMKID_CMDID + */ + +#define WMI_PMKID_LEN 16 + +typedef enum { + PMKID_DISABLE = 0, + PMKID_ENABLE = 1, +} PMKID_ENABLE_FLG; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u8 enable; /* PMKID_ENABLE_FLG */ + u8 pmkid[WMI_PMKID_LEN]; +} POSTPACK WMI_SET_PMKID_CMD; + +/* + * WMI_START_SCAN_CMD + */ +typedef enum { + WMI_LONG_SCAN = 0, + WMI_SHORT_SCAN = 1, +} WMI_SCAN_TYPE; + +typedef PREPACK struct { + u32 forceFgScan; + u32 isLegacy; /* For Legacy Cisco AP compatibility */ + u32 homeDwellTime; /* Maximum duration in the home channel(milliseconds) */ + u32 forceScanInterval; /* Time interval between scans (milliseconds)*/ + u8 scanType; /* WMI_SCAN_TYPE */ + u8 numChannels; /* how many channels follow */ + u16 channelList[1]; /* channels in Mhz */ +} POSTPACK WMI_START_SCAN_CMD; + +/* + * WMI_SET_SCAN_PARAMS_CMDID + */ +#define WMI_SHORTSCANRATIO_DEFAULT 3 +/* + * Warning: ScanCtrlFlag value of 0xFF is used to disable all flags in WMI_SCAN_PARAMS_CMD + * Do not add any more flags to WMI_SCAN_CTRL_FLAG_BITS + */ +typedef enum { + CONNECT_SCAN_CTRL_FLAGS = 0x01, /* set if can scan in the Connect cmd */ + SCAN_CONNECTED_CTRL_FLAGS = 0x02, /* set if scan for the SSID it is */ + /* already connected to */ + ACTIVE_SCAN_CTRL_FLAGS = 0x04, /* set if enable active scan */ + ROAM_SCAN_CTRL_FLAGS = 0x08, /* set if enable roam scan when bmiss and lowrssi */ + REPORT_BSSINFO_CTRL_FLAGS = 0x10, /* set if follows customer BSSINFO reporting rule */ + ENABLE_AUTO_CTRL_FLAGS = 0x20, /* if disabled, target doesn't + scan after a disconnect event */ + ENABLE_SCAN_ABORT_EVENT = 0x40 /* Scan complete event with canceled status will be generated when a scan is prempted before it gets completed */ +} WMI_SCAN_CTRL_FLAGS_BITS; + +#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS) +#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS) +#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS) +#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS) +#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS) +#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS) +#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT) + +#define DEFAULT_SCAN_CTRL_FLAGS (CONNECT_SCAN_CTRL_FLAGS| SCAN_CONNECTED_CTRL_FLAGS| ACTIVE_SCAN_CTRL_FLAGS| ROAM_SCAN_CTRL_FLAGS | ENABLE_AUTO_CTRL_FLAGS) + + +typedef PREPACK struct { + u16 fg_start_period; /* seconds */ + u16 fg_end_period; /* seconds */ + u16 bg_period; /* seconds */ + u16 maxact_chdwell_time; /* msec */ + u16 pas_chdwell_time; /* msec */ + u8 shortScanRatio; /* how many shorts scan for one long */ + u8 scanCtrlFlags; + u16 minact_chdwell_time; /* msec */ + u16 maxact_scan_per_ssid; /* max active scans per ssid */ + u32 max_dfsch_act_time; /* msecs */ +} POSTPACK WMI_SCAN_PARAMS_CMD; + +/* + * WMI_SET_BSS_FILTER_CMDID + */ +typedef enum { + NONE_BSS_FILTER = 0x0, /* no beacons forwarded */ + ALL_BSS_FILTER, /* all beacons forwarded */ + PROFILE_FILTER, /* only beacons matching profile */ + ALL_BUT_PROFILE_FILTER, /* all but beacons matching profile */ + CURRENT_BSS_FILTER, /* only beacons matching current BSS */ + ALL_BUT_BSS_FILTER, /* all but beacons matching BSS */ + PROBED_SSID_FILTER, /* beacons matching probed ssid */ + LAST_BSS_FILTER, /* marker only */ +} WMI_BSS_FILTER; + +typedef PREPACK struct { + u8 bssFilter; /* see WMI_BSS_FILTER */ + u8 reserved1; /* For alignment */ + u16 reserved2; /* For alignment */ + u32 ieMask; +} POSTPACK WMI_BSS_FILTER_CMD; + +/* + * WMI_SET_PROBED_SSID_CMDID + */ +#define MAX_PROBED_SSID_INDEX 9 + +typedef enum { + DISABLE_SSID_FLAG = 0, /* disables entry */ + SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */ + ANY_SSID_FLAG = 0x02, /* probes for any ssid */ +} WMI_SSID_FLAG; + +typedef PREPACK struct { + u8 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX */ + u8 flag; /* WMI_SSID_FLG */ + u8 ssidLength; + u8 ssid[32]; +} POSTPACK WMI_PROBED_SSID_CMD; + +/* + * WMI_SET_LISTEN_INT_CMDID + * The Listen interval is between 15 and 3000 TUs + */ +#define MIN_LISTEN_INTERVAL 15 +#define MAX_LISTEN_INTERVAL 5000 +#define MIN_LISTEN_BEACONS 1 +#define MAX_LISTEN_BEACONS 50 + +typedef PREPACK struct { + u16 listenInterval; + u16 numBeacons; +} POSTPACK WMI_LISTEN_INT_CMD; + +/* + * WMI_SET_BEACON_INT_CMDID + */ +typedef PREPACK struct { + u16 beaconInterval; +} POSTPACK WMI_BEACON_INT_CMD; + +/* + * WMI_SET_BMISS_TIME_CMDID + * valid values are between 1000 and 5000 TUs + */ + +#define MIN_BMISS_TIME 1000 +#define MAX_BMISS_TIME 5000 +#define MIN_BMISS_BEACONS 1 +#define MAX_BMISS_BEACONS 50 + +typedef PREPACK struct { + u16 bmissTime; + u16 numBeacons; +} POSTPACK WMI_BMISS_TIME_CMD; + +/* + * WMI_SET_POWER_MODE_CMDID + */ +typedef enum { + REC_POWER = 0x01, + MAX_PERF_POWER, +} WMI_POWER_MODE; + +typedef PREPACK struct { + u8 powerMode; /* WMI_POWER_MODE */ +} POSTPACK WMI_POWER_MODE_CMD; + +typedef PREPACK struct { + s8 status; /* WMI_SET_PARAMS_REPLY */ +} POSTPACK WMI_SET_PARAMS_REPLY; + +typedef PREPACK struct { + u32 opcode; + u32 length; + char buffer[1]; /* WMI_SET_PARAMS */ +} POSTPACK WMI_SET_PARAMS_CMD; + +typedef PREPACK struct { + u8 multicast_mac[ATH_MAC_LEN]; /* WMI_SET_MCAST_FILTER */ +} POSTPACK WMI_SET_MCAST_FILTER_CMD; + +typedef PREPACK struct { + u8 enable; /* WMI_MCAST_FILTER */ +} POSTPACK WMI_MCAST_FILTER_CMD; + +/* + * WMI_SET_POWER_PARAMS_CMDID + */ +typedef enum { + IGNORE_DTIM = 0x01, + NORMAL_DTIM = 0x02, + STICK_DTIM = 0x03, + AUTO_DTIM = 0x04, +} WMI_DTIM_POLICY; + +/* Policy to determnine whether TX should wakeup WLAN if sleeping */ +typedef enum { + TX_WAKEUP_UPON_SLEEP = 1, + TX_DONT_WAKEUP_UPON_SLEEP = 2 +} WMI_TX_WAKEUP_POLICY_UPON_SLEEP; + +/* + * Policy to determnine whether power save failure event should be sent to + * host during scanning + */ +typedef enum { + SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1, + IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2, +} POWER_SAVE_FAIL_EVENT_POLICY; + +typedef PREPACK struct { + u16 idle_period; /* msec */ + u16 pspoll_number; + u16 dtim_policy; + u16 tx_wakeup_policy; + u16 num_tx_to_wakeup; + u16 ps_fail_event_policy; +} POSTPACK WMI_POWER_PARAMS_CMD; + +/* Adhoc power save types */ +typedef enum { + ADHOC_PS_DISABLE=1, + ADHOC_PS_ATH=2, + ADHOC_PS_IEEE=3, + ADHOC_PS_OTHER=4, +} WMI_ADHOC_PS_TYPE; + +typedef PREPACK struct { + u8 power_saving; + u8 ttl; /* number of beacon periods */ + u16 atim_windows; /* msec */ + u16 timeout_value; /* msec */ +} POSTPACK WMI_IBSS_PM_CAPS_CMD; + +/* AP power save types */ +typedef enum { + AP_PS_DISABLE=1, + AP_PS_ATH=2, +} WMI_AP_PS_TYPE; + +typedef PREPACK struct { + u32 idle_time; /* in msec */ + u32 ps_period; /* in usec */ + u8 sleep_period; /* in ps periods */ + u8 psType; +} POSTPACK WMI_AP_PS_CMD; + +/* + * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID + */ +typedef enum { + IGNORE_TIM_ALL_QUEUES_APSD = 0, + PROCESS_TIM_ALL_QUEUES_APSD = 1, + IGNORE_TIM_SIMULATED_APSD = 2, + PROCESS_TIM_SIMULATED_APSD = 3, +} APSD_TIM_POLICY; + +typedef PREPACK struct { + u16 psPollTimeout; /* msec */ + u16 triggerTimeout; /* msec */ + u32 apsdTimPolicy; /* TIM behavior with ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */ + u32 simulatedAPSDTimPolicy; /* TIM behavior with simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */ +} POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD; + +/* + * WMI_SET_VOICE_PKT_SIZE_CMDID + */ +typedef PREPACK struct { + u16 voicePktSize; +} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD; + +/* + * WMI_SET_MAX_SP_LEN_CMDID + */ +typedef enum { + DELIVER_ALL_PKT = 0x0, + DELIVER_2_PKT = 0x1, + DELIVER_4_PKT = 0x2, + DELIVER_6_PKT = 0x3, +} APSD_SP_LEN_TYPE; + +typedef PREPACK struct { + u8 maxSPLen; +} POSTPACK WMI_SET_MAX_SP_LEN_CMD; + +/* + * WMI_SET_DISC_TIMEOUT_CMDID + */ +typedef PREPACK struct { + u8 disconnectTimeout; /* seconds */ +} POSTPACK WMI_DISC_TIMEOUT_CMD; + +typedef enum { + UPLINK_TRAFFIC = 0, + DNLINK_TRAFFIC = 1, + BIDIR_TRAFFIC = 2, +} DIR_TYPE; + +typedef enum { + DISABLE_FOR_THIS_AC = 0, + ENABLE_FOR_THIS_AC = 1, + ENABLE_FOR_ALL_AC = 2, +} VOICEPS_CAP_TYPE; + +typedef enum { + TRAFFIC_TYPE_APERIODIC = 0, + TRAFFIC_TYPE_PERIODIC = 1, +}TRAFFIC_TYPE; + +/* + * WMI_SYNCHRONIZE_CMDID + */ +typedef PREPACK struct { + u8 dataSyncMap; +} POSTPACK WMI_SYNC_CMD; + +/* + * WMI_CREATE_PSTREAM_CMDID + */ +typedef PREPACK struct { + u32 minServiceInt; /* in milli-sec */ + u32 maxServiceInt; /* in milli-sec */ + u32 inactivityInt; /* in milli-sec */ + u32 suspensionInt; /* in milli-sec */ + u32 serviceStartTime; + u32 minDataRate; /* in bps */ + u32 meanDataRate; /* in bps */ + u32 peakDataRate; /* in bps */ + u32 maxBurstSize; + u32 delayBound; + u32 minPhyRate; /* in bps */ + u32 sba; + u32 mediumTime; + u16 nominalMSDU; /* in octects */ + u16 maxMSDU; /* in octects */ + u8 trafficClass; + u8 trafficDirection; /* DIR_TYPE */ + u8 rxQueueNum; + u8 trafficType; /* TRAFFIC_TYPE */ + u8 voicePSCapability; /* VOICEPS_CAP_TYPE */ + u8 tsid; + u8 userPriority; /* 802.1D user priority */ + u8 nominalPHY; /* nominal phy rate */ +} POSTPACK WMI_CREATE_PSTREAM_CMD; + +/* + * WMI_DELETE_PSTREAM_CMDID + */ +typedef PREPACK struct { + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; + u8 trafficClass; + u8 tsid; +} POSTPACK WMI_DELETE_PSTREAM_CMD; + +/* + * WMI_SET_CHANNEL_PARAMS_CMDID + */ +typedef enum { + WMI_11A_MODE = 0x1, + WMI_11G_MODE = 0x2, + WMI_11AG_MODE = 0x3, + WMI_11B_MODE = 0x4, + WMI_11GONLY_MODE = 0x5, +} WMI_PHY_MODE; + +#define WMI_MAX_CHANNELS 32 + +typedef PREPACK struct { + u8 reserved1; + u8 scanParam; /* set if enable scan */ + u8 phyMode; /* see WMI_PHY_MODE */ + u8 numChannels; /* how many channels follow */ + u16 channelList[1]; /* channels in Mhz */ +} POSTPACK WMI_CHANNEL_PARAMS_CMD; + + +/* + * WMI_RSSI_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. + * Threshold values are in the ascending order, and should agree to: + * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal + * < highThreshold_upperVal) + */ + +typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{ + u32 pollTime; /* Polling time as a factor of LI */ + s16 thresholdAbove1_Val; /* lowest of upper */ + s16 thresholdAbove2_Val; + s16 thresholdAbove3_Val; + s16 thresholdAbove4_Val; + s16 thresholdAbove5_Val; + s16 thresholdAbove6_Val; /* highest of upper */ + s16 thresholdBelow1_Val; /* lowest of bellow */ + s16 thresholdBelow2_Val; + s16 thresholdBelow3_Val; + s16 thresholdBelow4_Val; + s16 thresholdBelow5_Val; + s16 thresholdBelow6_Val; /* highest of bellow */ + u8 weight; /* "alpha" */ + u8 reserved[3]; +} POSTPACK WMI_RSSI_THRESHOLD_PARAMS_CMD; + +/* + * WMI_SNR_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. + */ + +typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{ + u32 pollTime; /* Polling time as a factor of LI */ + u8 weight; /* "alpha" */ + u8 thresholdAbove1_Val; /* lowest of uppper*/ + u8 thresholdAbove2_Val; + u8 thresholdAbove3_Val; + u8 thresholdAbove4_Val; /* highest of upper */ + u8 thresholdBelow1_Val; /* lowest of bellow */ + u8 thresholdBelow2_Val; + u8 thresholdBelow3_Val; + u8 thresholdBelow4_Val; /* highest of bellow */ + u8 reserved[3]; +} POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD; + +/* + * WMI_LQ_THRESHOLD_PARAMS_CMDID + */ +typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS { + u8 enable; + u8 thresholdAbove1_Val; + u8 thresholdAbove2_Val; + u8 thresholdAbove3_Val; + u8 thresholdAbove4_Val; + u8 thresholdBelow1_Val; + u8 thresholdBelow2_Val; + u8 thresholdBelow3_Val; + u8 thresholdBelow4_Val; + u8 reserved[3]; +} POSTPACK WMI_LQ_THRESHOLD_PARAMS_CMD; + +typedef enum { + WMI_LPREAMBLE_DISABLED = 0, + WMI_LPREAMBLE_ENABLED +} WMI_LPREAMBLE_STATUS; + +typedef enum { + WMI_IGNORE_BARKER_IN_ERP = 0, + WMI_DONOT_IGNORE_BARKER_IN_ERP +} WMI_PREAMBLE_POLICY; + +typedef PREPACK struct { + u8 status; + u8 preamblePolicy; +}POSTPACK WMI_SET_LPREAMBLE_CMD; + +typedef PREPACK struct { + u16 threshold; +}POSTPACK WMI_SET_RTS_CMD; + +/* + * WMI_TARGET_ERROR_REPORT_BITMASK_CMDID + * Sets the error reporting event bitmask in target. Target clears it + * upon an error. Subsequent errors are counted, but not reported + * via event, unless the bitmask is set again. + */ +typedef PREPACK struct { + u32 bitmask; +} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK; + +/* + * WMI_SET_TX_PWR_CMDID + */ +typedef PREPACK struct { + u8 dbM; /* in dbM units */ +} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY; + +/* + * WMI_SET_ASSOC_INFO_CMDID + * + * A maximum of 2 private IEs can be sent in the [Re]Assoc request. + * A 3rd one, the CCX version IE can also be set from the host. + */ +#define WMI_MAX_ASSOC_INFO_TYPE 2 +#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */ + +#define WMI_MAX_ASSOC_INFO_LEN 240 + +typedef PREPACK struct { + u8 ieType; + u8 bufferSize; + u8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */ +} POSTPACK WMI_SET_ASSOC_INFO_CMD; + + +/* + * WMI_GET_TX_PWR_CMDID does not take any parameters + */ + +/* + * WMI_ADD_BAD_AP_CMDID + */ +#define WMI_MAX_BAD_AP_INDEX 1 + +typedef PREPACK struct { + u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_ADD_BAD_AP_CMD; + +/* + * WMI_DELETE_BAD_AP_CMDID + */ +typedef PREPACK struct { + u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ +} POSTPACK WMI_DELETE_BAD_AP_CMD; + +/* + * WMI_SET_ACCESS_PARAMS_CMDID + */ +#define WMI_DEFAULT_TXOP_ACPARAM 0 /* implies one MSDU */ +#define WMI_DEFAULT_ECWMIN_ACPARAM 4 /* corresponds to CWmin of 15 */ +#define WMI_DEFAULT_ECWMAX_ACPARAM 10 /* corresponds to CWmax of 1023 */ +#define WMI_MAX_CW_ACPARAM 15 /* maximum eCWmin or eCWmax */ +#define WMI_DEFAULT_AIFSN_ACPARAM 2 +#define WMI_MAX_AIFSN_ACPARAM 15 +typedef PREPACK struct { + u16 txop; /* in units of 32 usec */ + u8 eCWmin; + u8 eCWmax; + u8 aifsn; + u8 ac; +} POSTPACK WMI_SET_ACCESS_PARAMS_CMD; + + +/* + * WMI_SET_RETRY_LIMITS_CMDID + * + * This command is used to customize the number of retries the + * wlan device will perform on a given frame. + */ +#define WMI_MIN_RETRIES 2 +#define WMI_MAX_RETRIES 13 +typedef enum { + MGMT_FRAMETYPE = 0, + CONTROL_FRAMETYPE = 1, + DATA_FRAMETYPE = 2 +} WMI_FRAMETYPE; + +typedef PREPACK struct { + u8 frameType; /* WMI_FRAMETYPE */ + u8 trafficClass; /* applies only to DATA_FRAMETYPE */ + u8 maxRetries; + u8 enableNotify; +} POSTPACK WMI_SET_RETRY_LIMITS_CMD; + +/* + * WMI_SET_ROAM_CTRL_CMDID + * + * This command is used to influence the Roaming behaviour + * Set the host biases of the BSSs before setting the roam mode as bias + * based. + */ + +/* + * Different types of Roam Control + */ + +typedef enum { + WMI_FORCE_ROAM = 1, /* Roam to the specified BSSID */ + WMI_SET_ROAM_MODE = 2, /* default ,progd bias, no roam */ + WMI_SET_HOST_BIAS = 3, /* Set the Host Bias */ + WMI_SET_LOWRSSI_SCAN_PARAMS = 4, /* Set lowrssi Scan parameters */ +} WMI_ROAM_CTRL_TYPE; + +#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM +#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS + +/* + * ROAM MODES + */ + +typedef enum { + WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based ROAM */ + WMI_HOST_BIAS_ROAM_MODE = 2, /* HOST BIAS based ROAM */ + WMI_LOCK_BSS_MODE = 3 /* Lock to the Current BSS - no Roam */ +} WMI_ROAM_MODE; + +/* + * BSS HOST BIAS INFO + */ + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + s8 bias; +} POSTPACK WMI_BSS_BIAS; + +typedef PREPACK struct { + u8 numBss; + WMI_BSS_BIAS bssBias[1]; +} POSTPACK WMI_BSS_BIAS_INFO; + +typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS { + u16 lowrssi_scan_period; + s16 lowrssi_scan_threshold; + s16 lowrssi_roam_threshold; + u8 roam_rssi_floor; + u8 reserved[1]; /* For alignment */ +} POSTPACK WMI_LOWRSSI_SCAN_PARAMS; + +typedef PREPACK struct { + PREPACK union { + u8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */ + u8 roamMode; /* WMI_SET_ROAM_MODE */ + WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */ + WMI_LOWRSSI_SCAN_PARAMS lrScanParams; + } POSTPACK info; + u8 roamCtrlType ; +} POSTPACK WMI_SET_ROAM_CTRL_CMD; + +/* + * WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID + */ +typedef enum { + BT_WLAN_CONN_PRECDENCE_WLAN=0, /* Default */ + BT_WLAN_CONN_PRECDENCE_PAL, +} BT_WLAN_CONN_PRECEDENCE; + +typedef PREPACK struct { + u8 precedence; +} POSTPACK WMI_SET_BT_WLAN_CONN_PRECEDENCE; + +/* + * WMI_ENABLE_RM_CMDID + */ +typedef PREPACK struct { + u32 enable_radio_measurements; +} POSTPACK WMI_ENABLE_RM_CMD; + +/* + * WMI_SET_MAX_OFFHOME_DURATION_CMDID + */ +typedef PREPACK struct { + u8 max_offhome_duration; +} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD; + +typedef PREPACK struct { + u32 frequency; + u8 threshold; +} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD; +/*---------------------- BTCOEX RELATED -------------------------------------*/ +/*----------------------COMMON to AR6002 and AR6003 -------------------------*/ +typedef enum { + BT_STREAM_UNDEF = 0, + BT_STREAM_SCO, /* SCO stream */ + BT_STREAM_A2DP, /* A2DP stream */ + BT_STREAM_SCAN, /* BT Discovery or Page */ + BT_STREAM_ESCO, + BT_STREAM_MAX +} BT_STREAM_TYPE; + +typedef enum { + BT_PARAM_SCO_PSPOLL_LATENCY_ONE_FOURTH =1, + BT_PARAM_SCO_PSPOLL_LATENCY_HALF, + BT_PARAM_SCO_PSPOLL_LATENCY_THREE_FOURTH, +} BT_PARAMS_SCO_PSPOLL_LATENCY; + +typedef enum { + BT_PARAMS_SCO_STOMP_SCO_NEVER =1, + BT_PARAMS_SCO_STOMP_SCO_ALWAYS, + BT_PARAMS_SCO_STOMP_SCO_IN_LOWRSSI, +} BT_PARAMS_SCO_STOMP_RULES; + +typedef enum { + BT_STATUS_UNDEF = 0, + BT_STATUS_ON, + BT_STATUS_OFF, + BT_STATUS_MAX +} BT_STREAM_STATUS; + +typedef PREPACK struct { + u8 streamType; + u8 status; +} POSTPACK WMI_SET_BT_STATUS_CMD; + +typedef enum { + BT_ANT_TYPE_UNDEF=0, + BT_ANT_TYPE_DUAL, + BT_ANT_TYPE_SPLITTER, + BT_ANT_TYPE_SWITCH, + BT_ANT_TYPE_HIGH_ISO_DUAL +} BT_ANT_FRONTEND_CONFIG; + +typedef enum { + BT_COLOCATED_DEV_BTS4020=0, + BT_COLCATED_DEV_CSR , + BT_COLOCATED_DEV_VALKYRIE +} BT_COLOCATED_DEV_TYPE; + +/*********************** Applicable to AR6002 ONLY ******************************/ + +typedef enum { + BT_PARAM_SCO = 1, /* SCO stream parameters */ + BT_PARAM_A2DP , + BT_PARAM_ANTENNA_CONFIG, + BT_PARAM_COLOCATED_BT_DEVICE, + BT_PARAM_ACLCOEX, + BT_PARAM_11A_SEPARATE_ANT, + BT_PARAM_MAX +} BT_PARAM_TYPE; + + +#define BT_SCO_ALLOW_CLOSE_RANGE_OPT (1 << 0) +#define BT_SCO_FORCE_AWAKE_OPT (1 << 1) +#define BT_SCO_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2)) +#define BT_SCO_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1) +#define BT_SCO_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3)) +#define BT_SCO_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1) +#define BT_SCO_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF) +#define BT_SCO_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF) +#define BT_SCO_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8) +#define BT_SCO_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16) + +typedef PREPACK struct { + u32 numScoCyclesForceTrigger; /* Number SCO cycles after which + force a pspoll. default = 10 */ + u32 dataResponseTimeout; /* Timeout Waiting for Downlink pkt + in response for ps-poll, + default = 10 msecs */ + u32 stompScoRules; + u32 scoOptFlags; /* SCO Options Flags : + bits: meaning: + 0 Allow Close Range Optimization + 1 Force awake during close range + 2 If set use host supplied RSSI for OPT + 3 If set use host supplied RTS COUNT for OPT + 4..7 Unused + 8..15 Low Data Rate Min Cnt + 16..23 Low Data Rate Max Cnt + */ + + u8 stompDutyCyleVal; /* Sco cycles to limit ps-poll queuing + if stomped */ + u8 stompDutyCyleMaxVal; /*firm ware increases stomp duty cycle + gradually uptill this value on need basis*/ + u8 psPollLatencyFraction; /* Fraction of idle + period, within which + additional ps-polls + can be queued */ + u8 noSCOSlots; /* Number of SCO Tx/Rx slots. + HVx, EV3, 2EV3 = 2 */ + u8 noIdleSlots; /* Number of Bluetooth idle slots between + consecutive SCO Tx/Rx slots + HVx, EV3 = 4 + 2EV3 = 10 */ + u8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/ + u8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/ + u8 scoOptRtsCount; +} POSTPACK BT_PARAMS_SCO; + +#define BT_A2DP_ALLOW_CLOSE_RANGE_OPT (1 << 0) +#define BT_A2DP_FORCE_AWAKE_OPT (1 << 1) +#define BT_A2DP_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2)) +#define BT_A2DP_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1) +#define BT_A2DP_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3)) +#define BT_A2DP_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1) +#define BT_A2DP_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF) +#define BT_A2DP_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF) +#define BT_A2DP_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8) +#define BT_A2DP_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16) + +typedef PREPACK struct { + u32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for + wlan, after it identifies the idle time + default (30 msecs) */ + u32 a2dpBurstCntMin; /* Minimum number of bluetooth data frames + to replenish Wlan Usage limit (default 3) */ + u32 a2dpDataRespTimeout; + u32 a2dpOptFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 Force awake during close range + 2 If set use host supplied RSSI for OPT + 3 If set use host supplied RTS COUNT for OPT + 4..7 Unused + 8..15 Low Data Rate Min Cnt + 16..23 Low Data Rate Max Cnt + */ + u8 isCoLocatedBtRoleMaster; + u8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/ + u8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/ + u8 a2dpOptRtsCount; +}POSTPACK BT_PARAMS_A2DP; + +/* During BT ftp/ BT OPP or any another data based acl profile on bluetooth + (non a2dp).*/ +typedef PREPACK struct { + u32 aclWlanMediumUsageTime; /* Wlan usage time during Acl (non-a2dp) + coexistence (default 30 msecs) */ + u32 aclBtMediumUsageTime; /* Bt usage time during acl coexistence + (default 30 msecs)*/ + u32 aclDataRespTimeout; + u32 aclDetectTimeout; /* ACL coexistence enabled if we get + 10 Pkts in X msec(default 100 msecs) */ + u32 aclmaxPktCnt; /* No of ACL pkts to receive before + enabling ACL coex */ + +}POSTPACK BT_PARAMS_ACLCOEX; + +typedef PREPACK struct { + PREPACK union { + BT_PARAMS_SCO scoParams; + BT_PARAMS_A2DP a2dpParams; + BT_PARAMS_ACLCOEX aclCoexParams; + u8 antType; /* 0 -Disabled (default) + 1 - BT_ANT_TYPE_DUAL + 2 - BT_ANT_TYPE_SPLITTER + 3 - BT_ANT_TYPE_SWITCH */ + u8 coLocatedBtDev; /* 0 - BT_COLOCATED_DEV_BTS4020 (default) + 1 - BT_COLCATED_DEV_CSR + 2 - BT_COLOCATED_DEV_VALKYRIe + */ + } POSTPACK info; + u8 paramType ; +} POSTPACK WMI_SET_BT_PARAMS_CMD; + +/************************ END AR6002 BTCOEX *******************************/ +/*-----------------------AR6003 BTCOEX -----------------------------------*/ + +/* ---------------WMI_SET_BTCOEX_FE_ANT_CMDID --------------------------*/ +/* Indicates front end antenna configuration. This command needs to be issued + * right after initialization and after WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID. + * AR6003 enables coexistence and antenna switching based on the configuration. + */ +typedef enum { + WMI_BTCOEX_NOT_ENABLED = 0, + WMI_BTCOEX_FE_ANT_SINGLE =1, + WMI_BTCOEX_FE_ANT_DUAL=2, + WMI_BTCOEX_FE_ANT_DUAL_HIGH_ISO=3, + WMI_BTCOEX_FE_ANT_TYPE_MAX +}WMI_BTCOEX_FE_ANT_TYPE; + +typedef PREPACK struct { + u8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end + 2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end + (for isolations less 35dB, for higher isolation there + is not need to pass this command). + (not implemented) + */ +}POSTPACK WMI_SET_BTCOEX_FE_ANT_CMD; + +/* -------------WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID ----------------*/ +/* Indicate the bluetooth chip to the firmware. Firmware can have different algorithm based + * bluetooth chip type.Based on bluetooth device, different coexistence protocol would be used. + */ +typedef PREPACK struct { + u8 btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA) + 2 - CSR BT (3 wire PTA) + 3 - Atheros 3001 BT (3 wire PTA) + 4 - STE bluetooth (4-wire ePTA) + 5 - Atheros 3002 BT (4-wire MCI) + defaults= 3 (Atheros 3001 BT ) + */ +}POSTPACK WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD; + +/* -------------WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID ------------*/ +/* Configuration parameters during bluetooth inquiry and page. Page configuration + * is applicable only on interfaces which can distinguish page (applicable only for ePTA - + * STE bluetooth). + * Bluetooth inquiry start and end is indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID. + * During this the station will be power-save mode. + */ +typedef PREPACK struct { + u32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data + (via pspoll) is configured by this parameter. + "default = 10 ms" */ + + u32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state + for configured duration, after inquiry completion + . This is to ensure other bluetooth transactions + (RDP, SDP profiles, link key exchange ...etc) + goes through smoothly without wifi stomping. + default = 10 secs*/ + + u32 maxpageStomp; /*Applicable only for STE-BT interface. Currently not + used */ + u32 btInquiryPageFlag; /* Not used */ +}POSTPACK WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD; + +/*---------------------WMI_SET_BTCOEX_SCO_CONFIG_CMDID ---------------*/ +/* Configure SCO parameters. These parameters would be used whenever firmware is indicated + * of (e)SCO profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID). + * Configration of BTCOEX_SCO_CONFIG data structure are common configuration and applies + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data between sco gaps. + * Opt Mode - station is in awake state and access point can send data to station any time. + * BTCOEX_PSPOLLMODE_SCO_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_SCO_CONFIG - Configuration applied only during opt mode. + */ +#define WMI_SCO_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_SCO_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1) +#define WMI_SCO_CONFIG_FLAG_IS_BT_MASTER (1 << 2) +#define WMI_SCO_CONFIG_FLAG_FW_DETECT_OF_PER (1 << 3) +typedef PREPACK struct { + u32 scoSlots; /* Number of SCO Tx/Rx slots. + HVx, EV3, 2EV3 = 2 */ + u32 scoIdleSlots; /* Number of Bluetooth idle slots between + consecutive SCO Tx/Rx slots + HVx, EV3 = 4 + 2EV3 = 10 + */ + u32 scoFlags; /* SCO Options Flags : + bits: meaning: + 0 Allow Close Range Optimization + 1 Is EDR capable or Not + 2 IS Co-located Bt role Master + 3 Firmware determines the periodicity of SCO. + */ + + u32 linkId; /* applicable to STE-BT - not used */ +}POSTPACK BTCOEX_SCO_CONFIG; + +typedef PREPACK struct { + u32 scoCyclesForceTrigger; /* Number SCO cycles after which + force a pspoll. default = 10 */ + u32 scoDataResponseTimeout; /* Timeout Waiting for Downlink pkt + in response for ps-poll, + default = 20 msecs */ + + u32 scoStompDutyCyleVal; /* not implemented */ + + u32 scoStompDutyCyleMaxVal; /*Not implemented */ + + u32 scoPsPollLatencyFraction; /* Fraction of idle + period, within which + additional ps-polls can be queued + 1 - 1/4 of idle duration + 2 - 1/2 of idle duration + 3 - 3/4 of idle duration + default =2 (1/2) + */ +}POSTPACK BTCOEX_PSPOLLMODE_SCO_CONFIG; + +typedef PREPACK struct { + u32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in + opt mode. If exceeds the configured value, + switch to ps-poll mode + default = 3 */ + + u32 scoContStompMax; /* max number of continuous stomp allowed in opt mode. + if exceeded switch to pspoll mode + default = 3 */ + + u32 scoMinlowRateMbps; /* Low rate threshold */ + + u32 scoLowRateCnt; /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms. + If exceeded switch/stay to ps-poll mode, lower stay in opt mode. + default = 36 + */ + + u32 scoHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/ + ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms, + if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode. + default = 5 (80% of high rates) + */ + + u32 scoMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates + max number of aggregates if it was negogiated to higher value + default = 1 + Recommended value Basic rate headsets = 1, EDR (2-EV3) =4. + */ +}POSTPACK BTCOEX_OPTMODE_SCO_CONFIG; + +typedef PREPACK struct { + u32 scanInterval; + u32 maxScanStompCnt; +}POSTPACK BTCOEX_WLANSCAN_SCO_CONFIG; + +typedef PREPACK struct { + BTCOEX_SCO_CONFIG scoConfig; + BTCOEX_PSPOLLMODE_SCO_CONFIG scoPspollConfig; + BTCOEX_OPTMODE_SCO_CONFIG scoOptModeConfig; + BTCOEX_WLANSCAN_SCO_CONFIG scoWlanScanConfig; +}POSTPACK WMI_SET_BTCOEX_SCO_CONFIG_CMD; + +/* ------------------WMI_SET_BTCOEX_A2DP_CONFIG_CMDID -------------------*/ +/* Configure A2DP profile parameters. These parameters would be used whenver firmware is indicated + * of A2DP profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID). + * Configuration of BTCOEX_A2DP_CONFIG data structure are common configuration and applies to + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data between a2dp data bursts. + * Opt Mode - station is in power save during a2dp bursts and awake in the gaps. + * BTCOEX_PSPOLLMODE_A2DP_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_A2DP_CONFIG - Configuration applied only during opt mode. + */ + +#define WMI_A2DP_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_A2DP_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1) +#define WMI_A2DP_CONFIG_FLAG_IS_BT_ROLE_MASTER (1 << 2) +#define WMI_A2DP_CONFIG_FLAG_IS_A2DP_HIGH_PRI (1 << 3) +#define WMI_A2DP_CONFIG_FLAG_FIND_BT_ROLE (1 << 4) + +typedef PREPACK struct { + u32 a2dpFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 IS EDR capable + 2 IS Co-located Bt role Master + 3 a2dp traffic is high priority + 4 Fw detect the role of bluetooth. + */ + u32 linkId; /* Applicable only to STE-BT - not used */ + +}POSTPACK BTCOEX_A2DP_CONFIG; + +typedef PREPACK struct { + u32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for + wlan, after it identifies the idle time + default (30 msecs) */ + + u32 a2dpMinBurstCnt; /* Minimum number of bluetooth data frames + to replenish Wlan Usage limit (default 3) */ + + u32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink + by stomping on bluetooth + after ps-poll is acknowledged. + default = 20 ms + */ +}POSTPACK BTCOEX_PSPOLLMODE_A2DP_CONFIG; + +typedef PREPACK struct { + u32 a2dpMinlowRateMbps; /* Low rate threshold */ + + u32 a2dpLowRateCnt; /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms. + If exceeded switch/stay to ps-poll mode, lower stay in opt mode. + default = 36 + */ + + u32 a2dpHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/ + ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms, + if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode. + default = 5 (80% of high rates) + */ + + u32 a2dpMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates + max number of aggregates if it was negogiated to higher value + default = 1 + Recommended value Basic rate headsets = 1, EDR (2-EV3) =8. + */ + u32 a2dpPktStompCnt; /*number of a2dp pkts that can be stomped per burst. + default = 6*/ + +}POSTPACK BTCOEX_OPTMODE_A2DP_CONFIG; + +typedef PREPACK struct { + BTCOEX_A2DP_CONFIG a2dpConfig; + BTCOEX_PSPOLLMODE_A2DP_CONFIG a2dppspollConfig; + BTCOEX_OPTMODE_A2DP_CONFIG a2dpOptConfig; +}POSTPACK WMI_SET_BTCOEX_A2DP_CONFIG_CMD; + +/*------------ WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID---------------------*/ +/* Configure non-A2dp ACL profile parameters.The starts of ACL profile can either be + * indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID orenabled via firmware detection + * which is configured via "aclCoexFlags". + * Configration of BTCOEX_ACLCOEX_CONFIG data structure are common configuration and applies + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data during wlan medium. + * Opt Mode - station is in power save during bluetooth medium time and awake during wlan duration. + * (Not implemented yet) + * + * BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_ACLCOEX_CONFIG - Configuration applied only during opt mode. + */ + +#define WMI_ACLCOEX_FLAGS_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1) + +typedef PREPACK struct { + u32 aclWlanMediumDur; /* Wlan usage time during Acl (non-a2dp) + coexistence (default 30 msecs) + */ + + u32 aclBtMediumDur; /* Bt usage time during acl coexistence + (default 30 msecs) + */ + + u32 aclDetectTimeout; /* BT activity observation time limit. + In this time duration, number of bt pkts are counted. + If the Cnt reaches "aclPktCntLowerLimit" value + for "aclIterToEnableCoex" iteration continuously, + firmware gets into ACL coexistence mode. + Similarly, if bt traffic count during ACL coexistence + has not reached "aclPktCntLowerLimit" continuously + for "aclIterToEnableCoex", then ACL coexistence is + disabled. + -default 100 msecs + */ + + u32 aclPktCntLowerLimit; /* Acl Pkt Cnt to be received in duration of + "aclDetectTimeout" for + "aclIterForEnDis" times to enabling ACL coex. + Similar logic is used to disable acl coexistence. + (If "aclPktCntLowerLimit" cnt of acl pkts + are not seen by the for "aclIterForEnDis" + then acl coexistence is disabled). + default = 10 + */ + + u32 aclIterForEnDis; /* number of Iteration of "aclPktCntLowerLimit" for Enabling and + Disabling Acl Coexistence. + default = 3 + */ + + u32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than + "aclPktCntUpperLimit" seen in "aclDetectTimeout", + ACL coexistence is enabled right away. + - default 15*/ + + u32 aclCoexFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 disable Firmware detection + (Currently supported configuration is aclCoexFlags =0) + */ + u32 linkId; /* Applicable only for STE-BT - not used */ + +}POSTPACK BTCOEX_ACLCOEX_CONFIG; + +typedef PREPACK struct { + u32 aclDataRespTimeout; /* Max duration firmware waits for downlink + by stomping on bluetooth + after ps-poll is acknowledged. + default = 20 ms */ + +}POSTPACK BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG; + + +/* Not implemented yet*/ +typedef PREPACK struct { + u32 aclCoexMinlowRateMbps; + u32 aclCoexLowRateCnt; + u32 aclCoexHighPktRatio; + u32 aclCoexMaxAggrSize; + u32 aclPktStompCnt; +}POSTPACK BTCOEX_OPTMODE_ACLCOEX_CONFIG; + +typedef PREPACK struct { + BTCOEX_ACLCOEX_CONFIG aclCoexConfig; + BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG aclCoexPspollConfig; + BTCOEX_OPTMODE_ACLCOEX_CONFIG aclCoexOptConfig; +}POSTPACK WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD; + +/* -----------WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ------------------*/ +typedef enum { + WMI_BTCOEX_BT_PROFILE_SCO =1, + WMI_BTCOEX_BT_PROFILE_A2DP, + WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE, + WMI_BTCOEX_BT_PROFILE_ACLCOEX, +}WMI_BTCOEX_BT_PROFILE; + +typedef PREPACK struct { + u32 btProfileType; + u32 btOperatingStatus; + u32 btLinkId; +}WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD; + +/*--------------------- WMI_SET_BTCOEX_DEBUG_CMDID ---------------------*/ +/* Used for firmware development and debugging */ +typedef PREPACK struct { + u32 btcoexDbgParam1; + u32 btcoexDbgParam2; + u32 btcoexDbgParam3; + u32 btcoexDbgParam4; + u32 btcoexDbgParam5; +}WMI_SET_BTCOEX_DEBUG_CMD; + +/*---------------------WMI_GET_BTCOEX_CONFIG_CMDID --------------------- */ +/* Command to firmware to get configuration parameters of the bt profile + * reported via WMI_BTCOEX_CONFIG_EVENTID */ +typedef PREPACK struct { + u32 btProfileType; /* 1 - SCO + 2 - A2DP + 3 - INQUIRY_PAGE + 4 - ACLCOEX + */ + u32 linkId; /* not used */ +}WMI_GET_BTCOEX_CONFIG_CMD; + +/*------------------WMI_REPORT_BTCOEX_CONFIG_EVENTID------------------- */ +/* Event from firmware to host, sent in response to WMI_GET_BTCOEX_CONFIG_CMDID + * */ +typedef PREPACK struct { + u32 btProfileType; + u32 linkId; /* not used */ + PREPACK union { + WMI_SET_BTCOEX_SCO_CONFIG_CMD scoConfigCmd; + WMI_SET_BTCOEX_A2DP_CONFIG_CMD a2dpConfigCmd; + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD aclcoexConfig; + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD btinquiryPageConfigCmd; + } POSTPACK info; +} POSTPACK WMI_BTCOEX_CONFIG_EVENT; + +/*------------- WMI_REPORT_BTCOEX_BTCOEX_STATS_EVENTID--------------------*/ +/* Used for firmware development and debugging*/ +typedef PREPACK struct { + u32 highRatePktCnt; + u32 firstBmissCnt; + u32 psPollFailureCnt; + u32 nullFrameFailureCnt; + u32 optModeTransitionCnt; +}BTCOEX_GENERAL_STATS; + +typedef PREPACK struct { + u32 scoStompCntAvg; + u32 scoStompIn100ms; + u32 scoMaxContStomp; + u32 scoAvgNoRetries; + u32 scoMaxNoRetriesIn100ms; +}BTCOEX_SCO_STATS; + +typedef PREPACK struct { + u32 a2dpBurstCnt; + u32 a2dpMaxBurstCnt; + u32 a2dpAvgIdletimeIn100ms; + u32 a2dpAvgStompCnt; +}BTCOEX_A2DP_STATS; + +typedef PREPACK struct { + u32 aclPktCntInBtTime; + u32 aclStompCntInWlanTime; + u32 aclPktCntIn100ms; +}BTCOEX_ACLCOEX_STATS; + +typedef PREPACK struct { + BTCOEX_GENERAL_STATS coexStats; + BTCOEX_SCO_STATS scoStats; + BTCOEX_A2DP_STATS a2dpStats; + BTCOEX_ACLCOEX_STATS aclCoexStats; +}WMI_BTCOEX_STATS_EVENT; + + +/*--------------------------END OF BTCOEX -------------------------------------*/ +typedef PREPACK struct { + u32 sleepState; +}WMI_REPORT_SLEEP_STATE_EVENT; + +typedef enum { + WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP =0, + WMI_REPORT_SLEEP_STATUS_IS_AWAKE +} WMI_REPORT_SLEEP_STATUS; +typedef enum { + DISCONN_EVT_IN_RECONN = 0, /* default */ + NO_DISCONN_EVT_IN_RECONN +} TARGET_EVENT_REPORT_CONFIG; + +typedef PREPACK struct { + u32 evtConfig; +} POSTPACK WMI_SET_TARGET_EVENT_REPORT_CMD; + + +typedef PREPACK struct { + u16 cmd_buf_sz; /* HCI cmd buffer size */ + u8 buf[1]; /* Absolute HCI cmd */ +} POSTPACK WMI_HCI_CMD; + +/* + * Command Replies + */ + +/* + * WMI_GET_CHANNEL_LIST_CMDID reply + */ +typedef PREPACK struct { + u8 reserved1; + u8 numChannels; /* number of channels in reply */ + u16 channelList[1]; /* channel in Mhz */ +} POSTPACK WMI_CHANNEL_LIST_REPLY; + +typedef enum { + A_SUCCEEDED = 0, + A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250, + A_SUCCEEDED_MODIFY_STREAM=251, + A_FAILED_INVALID_STREAM = 252, + A_FAILED_MAX_THINSTREAMS = 253, + A_FAILED_CREATE_REMOVE_PSTREAM_FIRST = 254, +} PSTREAM_REPLY_STATUS; + +typedef PREPACK struct { + u8 status; /* PSTREAM_REPLY_STATUS */ + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficClass; + u8 trafficDirection; /* DIR_TYPE */ +} POSTPACK WMI_CRE_PRIORITY_STREAM_REPLY; + +typedef PREPACK struct { + u8 status; /* PSTREAM_REPLY_STATUS */ + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; /* DIR_TYPE */ + u8 trafficClass; +} POSTPACK WMI_DEL_PRIORITY_STREAM_REPLY; + +/* + * List of Events (target to host) + */ +typedef enum { + WMI_READY_EVENTID = 0x1001, + WMI_CONNECT_EVENTID, + WMI_DISCONNECT_EVENTID, + WMI_BSSINFO_EVENTID, + WMI_CMDERROR_EVENTID, + WMI_REGDOMAIN_EVENTID, + WMI_PSTREAM_TIMEOUT_EVENTID, + WMI_NEIGHBOR_REPORT_EVENTID, + WMI_TKIP_MICERR_EVENTID, + WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */ + WMI_REPORT_STATISTICS_EVENTID, + WMI_RSSI_THRESHOLD_EVENTID, + WMI_ERROR_REPORT_EVENTID, + WMI_OPT_RX_FRAME_EVENTID, + WMI_REPORT_ROAM_TBL_EVENTID, + WMI_EXTENSION_EVENTID, + WMI_CAC_EVENTID, + WMI_SNR_THRESHOLD_EVENTID, + WMI_LQ_THRESHOLD_EVENTID, + WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */ + WMI_REPORT_ROAM_DATA_EVENTID, + WMI_TEST_EVENTID, + WMI_APLIST_EVENTID, + WMI_GET_WOW_LIST_EVENTID, + WMI_GET_PMKID_LIST_EVENTID, + WMI_CHANNEL_CHANGE_EVENTID, + WMI_PEER_NODE_EVENTID, + WMI_PSPOLL_EVENTID, + WMI_DTIMEXPIRY_EVENTID, + WMI_WLAN_VERSION_EVENTID, + WMI_SET_PARAMS_REPLY_EVENTID, + WMI_ADDBA_REQ_EVENTID, /*0x1020 */ + WMI_ADDBA_RESP_EVENTID, + WMI_DELBA_REQ_EVENTID, + WMI_TX_COMPLETE_EVENTID, + WMI_HCI_EVENT_EVENTID, + WMI_ACL_DATA_EVENTID, + WMI_REPORT_SLEEP_STATE_EVENTID, +#ifdef WAPI_ENABLE + WMI_WAPI_REKEY_EVENTID, +#endif + WMI_REPORT_BTCOEX_STATS_EVENTID, + WMI_REPORT_BTCOEX_CONFIG_EVENTID, + WMI_GET_PMK_EVENTID, + + /* DFS Events */ + WMI_DFS_HOST_ATTACH_EVENTID, + WMI_DFS_HOST_INIT_EVENTID, + WMI_DFS_RESET_DELAYLINES_EVENTID, + WMI_DFS_RESET_RADARQ_EVENTID, + WMI_DFS_RESET_AR_EVENTID, + WMI_DFS_RESET_ARQ_EVENTID, + WMI_DFS_SET_DUR_MULTIPLIER_EVENTID, + WMI_DFS_SET_BANGRADAR_EVENTID, + WMI_DFS_SET_DEBUGLEVEL_EVENTID, + WMI_DFS_PHYERR_EVENTID, + /* CCX Evants */ + WMI_CCX_RM_STATUS_EVENTID, + + /* P2P Events */ + WMI_P2P_GO_NEG_RESULT_EVENTID, + + WMI_WAC_SCAN_DONE_EVENTID, + WMI_WAC_REPORT_BSS_EVENTID, + WMI_WAC_START_WPS_EVENTID, + WMI_WAC_CTRL_REQ_REPLY_EVENTID, + + /* RFKILL Events */ + WMI_RFKILL_STATE_CHANGE_EVENTID, + WMI_RFKILL_GET_MODE_CMD_EVENTID, + WMI_THIN_RESERVED_START_EVENTID = 0x8000, + + /* + * Events in this range are reserved for thinmode + * See wmi_thin.h for actual definitions + */ + WMI_THIN_RESERVED_END_EVENTID = 0x8fff, + + WMI_SET_CHANNEL_EVENTID, + WMI_ASSOC_REQ_EVENTID, + + /* generic ACS event */ + WMI_ACS_EVENTID, + WMI_REPORT_WMM_PARAMS_EVENTID +} WMI_EVENT_ID; + + +typedef enum { + WMI_11A_CAPABILITY = 1, + WMI_11G_CAPABILITY = 2, + WMI_11AG_CAPABILITY = 3, + WMI_11NA_CAPABILITY = 4, + WMI_11NG_CAPABILITY = 5, + WMI_11NAG_CAPABILITY = 6, + // END CAPABILITY + WMI_11N_CAPABILITY_OFFSET = (WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY), +} WMI_PHY_CAPABILITY; + +typedef PREPACK struct { + u8 macaddr[ATH_MAC_LEN]; + u8 phyCapability; /* WMI_PHY_CAPABILITY */ +} POSTPACK WMI_READY_EVENT_1; + +typedef PREPACK struct { + u32 sw_version; + u32 abi_version; + u8 macaddr[ATH_MAC_LEN]; + u8 phyCapability; /* WMI_PHY_CAPABILITY */ +} POSTPACK WMI_READY_EVENT_2; + +#if defined(ATH_TARGET) +#ifdef AR6002_REV2 +#define WMI_READY_EVENT WMI_READY_EVENT_1 /* AR6002_REV2 target code */ +#else +#define WMI_READY_EVENT WMI_READY_EVENT_2 /* AR6001, AR6002_REV4, AR6002_REV5 */ +#endif +#else +#define WMI_READY_EVENT WMI_READY_EVENT_2 /* host code */ +#endif + + +/* + * Connect Event + */ +typedef PREPACK struct { + u16 channel; + u8 bssid[ATH_MAC_LEN]; + u16 listenInterval; + u16 beaconInterval; + u32 networkType; + u8 beaconIeLen; + u8 assocReqLen; + u8 assocRespLen; + u8 assocInfo[1]; +} POSTPACK WMI_CONNECT_EVENT; + +/* + * Disconnect Event + */ +typedef enum { + NO_NETWORK_AVAIL = 0x01, + LOST_LINK = 0x02, /* bmiss */ + DISCONNECT_CMD = 0x03, + BSS_DISCONNECTED = 0x04, + AUTH_FAILED = 0x05, + ASSOC_FAILED = 0x06, + NO_RESOURCES_AVAIL = 0x07, + CSERV_DISCONNECT = 0x08, + INVALID_PROFILE = 0x0a, + DOT11H_CHANNEL_SWITCH = 0x0b, + PROFILE_MISMATCH = 0x0c, + CONNECTION_EVICTED = 0x0d, + IBSS_MERGE = 0xe, +} WMI_DISCONNECT_REASON; + +typedef PREPACK struct { + u16 protocolReasonStatus; /* reason code, see 802.11 spec. */ + u8 bssid[ATH_MAC_LEN]; /* set if known */ + u8 disconnectReason ; /* see WMI_DISCONNECT_REASON */ + u8 assocRespLen; + u8 assocInfo[1]; +} POSTPACK WMI_DISCONNECT_EVENT; + +/* + * BSS Info Event. + * Mechanism used to inform host of the presence and characteristic of + * wireless networks present. Consists of bss info header followed by + * the beacon or probe-response frame body. The 802.11 header is not included. + */ +typedef enum { + BEACON_FTYPE = 0x1, + PROBERESP_FTYPE, + ACTION_MGMT_FTYPE, + PROBEREQ_FTYPE, +} WMI_BI_FTYPE; + +enum { + BSS_ELEMID_CHANSWITCH = 0x01, + BSS_ELEMID_ATHEROS = 0x02, +}; + +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_BI_FTYPE */ + u8 snr; + s16 rssi; + u8 bssid[ATH_MAC_LEN]; + u32 ieMask; +} POSTPACK WMI_BSS_INFO_HDR; + +/* + * BSS INFO HDR version 2.0 + * With 6 bytes HTC header and 6 bytes of WMI header + * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management + * header space. + * - Reduce the ieMask to 2 bytes as only two bit flags are used + * - Remove rssi and compute it on the host. rssi = snr - 95 + */ +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_BI_FTYPE */ + u8 snr; + u8 bssid[ATH_MAC_LEN]; + u16 ieMask; +} POSTPACK WMI_BSS_INFO_HDR2; + +/* + * Command Error Event + */ +typedef enum { + INVALID_PARAM = 0x01, + ILLEGAL_STATE = 0x02, + INTERNAL_ERROR = 0x03, +} WMI_ERROR_CODE; + +typedef PREPACK struct { + u16 commandId; + u8 errorCode; +} POSTPACK WMI_CMD_ERROR_EVENT; + +/* + * New Regulatory Domain Event + */ +typedef PREPACK struct { + u32 regDomain; +} POSTPACK WMI_REG_DOMAIN_EVENT; + +typedef PREPACK struct { + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; + u8 trafficClass; +} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT; + +typedef PREPACK struct { + u8 reserve1; + u8 reserve2; + u8 reserve3; + u8 trafficClass; +} POSTPACK WMI_ACM_REJECT_EVENT; + +/* + * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform + * the host of BSS's it has found that matches the current profile. + * It can be used by the host to cache PMKs and/to initiate pre-authentication + * if the BSS supports it. The first bssid is always the current associated + * BSS. + * The bssid and bssFlags information repeats according to the number + * or APs reported. + */ +typedef enum { + WMI_DEFAULT_BSS_FLAGS = 0x00, + WMI_PREAUTH_CAPABLE_BSS = 0x01, + WMI_PMKID_VALID_BSS = 0x02, +} WMI_BSS_FLAGS; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u8 bssFlags; /* see WMI_BSS_FLAGS */ +} POSTPACK WMI_NEIGHBOR_INFO; + +typedef PREPACK struct { + s8 numberOfAps; + WMI_NEIGHBOR_INFO neighbor[1]; +} POSTPACK WMI_NEIGHBOR_REPORT_EVENT; + +/* + * TKIP MIC Error Event + */ +typedef PREPACK struct { + u8 keyid; + u8 ismcast; +} POSTPACK WMI_TKIP_MICERR_EVENT; + +/* + * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new) + */ +typedef PREPACK struct { + s32 status; +} POSTPACK WMI_SCAN_COMPLETE_EVENT; + +#define MAX_OPT_DATA_LEN 1400 + +/* + * WMI_SET_ADHOC_BSSID_CMDID + */ +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_SET_ADHOC_BSSID_CMD; + +/* + * WMI_SET_OPT_MODE_CMDID + */ +typedef enum { + SPECIAL_OFF, + SPECIAL_ON, +} OPT_MODE_TYPE; + +typedef PREPACK struct { + u8 optMode; +} POSTPACK WMI_SET_OPT_MODE_CMD; + +/* + * WMI_TX_OPT_FRAME_CMDID + */ +typedef enum { + OPT_PROBE_REQ = 0x01, + OPT_PROBE_RESP = 0x02, + OPT_CPPP_START = 0x03, + OPT_CPPP_STOP = 0x04, +} WMI_OPT_FTYPE; + +typedef PREPACK struct { + u16 optIEDataLen; + u8 frmType; + u8 dstAddr[ATH_MAC_LEN]; + u8 bssid[ATH_MAC_LEN]; + u8 reserved; /* For alignment */ + u8 optIEData[1]; +} POSTPACK WMI_OPT_TX_FRAME_CMD; + +/* + * Special frame receive Event. + * Mechanism used to inform host of the receiption of the special frames. + * Consists of special frame info header followed by special frame body. + * The 802.11 header is not included. + */ +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_OPT_FTYPE */ + s8 snr; + u8 srcAddr[ATH_MAC_LEN]; + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_OPT_RX_INFO_HDR; + +/* + * Reporting statistics. + */ +typedef PREPACK struct { + u32 tx_packets; + u32 tx_bytes; + u32 tx_unicast_pkts; + u32 tx_unicast_bytes; + u32 tx_multicast_pkts; + u32 tx_multicast_bytes; + u32 tx_broadcast_pkts; + u32 tx_broadcast_bytes; + u32 tx_rts_success_cnt; + u32 tx_packet_per_ac[4]; + u32 tx_errors_per_ac[4]; + + u32 tx_errors; + u32 tx_failed_cnt; + u32 tx_retry_cnt; + u32 tx_mult_retry_cnt; + u32 tx_rts_fail_cnt; + s32 tx_unicast_rate; +}POSTPACK tx_stats_t; + +typedef PREPACK struct { + u32 rx_packets; + u32 rx_bytes; + u32 rx_unicast_pkts; + u32 rx_unicast_bytes; + u32 rx_multicast_pkts; + u32 rx_multicast_bytes; + u32 rx_broadcast_pkts; + u32 rx_broadcast_bytes; + u32 rx_fragment_pkt; + + u32 rx_errors; + u32 rx_crcerr; + u32 rx_key_cache_miss; + u32 rx_decrypt_err; + u32 rx_duplicate_frames; + s32 rx_unicast_rate; +}POSTPACK rx_stats_t; + +typedef PREPACK struct { + u32 tkip_local_mic_failure; + u32 tkip_counter_measures_invoked; + u32 tkip_replays; + u32 tkip_format_errors; + u32 ccmp_format_errors; + u32 ccmp_replays; +}POSTPACK tkip_ccmp_stats_t; + +typedef PREPACK struct { + u32 power_save_failure_cnt; + u16 stop_tx_failure_cnt; + u16 atim_tx_failure_cnt; + u16 atim_rx_failure_cnt; + u16 bcn_rx_failure_cnt; +}POSTPACK pm_stats_t; + +typedef PREPACK struct { + u32 cs_bmiss_cnt; + u32 cs_lowRssi_cnt; + u16 cs_connect_cnt; + u16 cs_disconnect_cnt; + s16 cs_aveBeacon_rssi; + u16 cs_roam_count; + s16 cs_rssi; + u8 cs_snr; + u8 cs_aveBeacon_snr; + u8 cs_lastRoam_msec; +} POSTPACK cserv_stats_t; + +typedef PREPACK struct { + tx_stats_t tx_stats; + rx_stats_t rx_stats; + tkip_ccmp_stats_t tkipCcmpStats; +}POSTPACK wlan_net_stats_t; + +typedef PREPACK struct { + u32 arp_received; + u32 arp_matched; + u32 arp_replied; +} POSTPACK arp_stats_t; + +typedef PREPACK struct { + u32 wow_num_pkts_dropped; + u16 wow_num_events_discarded; + u8 wow_num_host_pkt_wakeups; + u8 wow_num_host_event_wakeups; +} POSTPACK wlan_wow_stats_t; + +typedef PREPACK struct { + u32 lqVal; + s32 noise_floor_calibation; + pm_stats_t pmStats; + wlan_net_stats_t txrxStats; + wlan_wow_stats_t wowStats; + arp_stats_t arpStats; + cserv_stats_t cservStats; +} POSTPACK WMI_TARGET_STATS; + +/* + * WMI_RSSI_THRESHOLD_EVENTID. + * Indicate the RSSI events to host. Events are indicated when we breach a + * thresold value. + */ +typedef enum{ + WMI_RSSI_THRESHOLD1_ABOVE = 0, + WMI_RSSI_THRESHOLD2_ABOVE, + WMI_RSSI_THRESHOLD3_ABOVE, + WMI_RSSI_THRESHOLD4_ABOVE, + WMI_RSSI_THRESHOLD5_ABOVE, + WMI_RSSI_THRESHOLD6_ABOVE, + WMI_RSSI_THRESHOLD1_BELOW, + WMI_RSSI_THRESHOLD2_BELOW, + WMI_RSSI_THRESHOLD3_BELOW, + WMI_RSSI_THRESHOLD4_BELOW, + WMI_RSSI_THRESHOLD5_BELOW, + WMI_RSSI_THRESHOLD6_BELOW +}WMI_RSSI_THRESHOLD_VAL; + +typedef PREPACK struct { + s16 rssi; + u8 range; +}POSTPACK WMI_RSSI_THRESHOLD_EVENT; + +/* + * WMI_ERROR_REPORT_EVENTID + */ +typedef enum{ + WMI_TARGET_PM_ERR_FAIL = 0x00000001, + WMI_TARGET_KEY_NOT_FOUND = 0x00000002, + WMI_TARGET_DECRYPTION_ERR = 0x00000004, + WMI_TARGET_BMISS = 0x00000008, + WMI_PSDISABLE_NODE_JOIN = 0x00000010, + WMI_TARGET_COM_ERR = 0x00000020, + WMI_TARGET_FATAL_ERR = 0x00000040 +} WMI_TARGET_ERROR_VAL; + +typedef PREPACK struct { + u32 errorVal; +}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT; + +typedef PREPACK struct { + u8 retrys; +}POSTPACK WMI_TX_RETRY_ERR_EVENT; + +typedef enum{ + WMI_SNR_THRESHOLD1_ABOVE = 1, + WMI_SNR_THRESHOLD1_BELOW, + WMI_SNR_THRESHOLD2_ABOVE, + WMI_SNR_THRESHOLD2_BELOW, + WMI_SNR_THRESHOLD3_ABOVE, + WMI_SNR_THRESHOLD3_BELOW, + WMI_SNR_THRESHOLD4_ABOVE, + WMI_SNR_THRESHOLD4_BELOW +} WMI_SNR_THRESHOLD_VAL; + +typedef PREPACK struct { + u8 range; /* WMI_SNR_THRESHOLD_VAL */ + u8 snr; +}POSTPACK WMI_SNR_THRESHOLD_EVENT; + +typedef enum{ + WMI_LQ_THRESHOLD1_ABOVE = 1, + WMI_LQ_THRESHOLD1_BELOW, + WMI_LQ_THRESHOLD2_ABOVE, + WMI_LQ_THRESHOLD2_BELOW, + WMI_LQ_THRESHOLD3_ABOVE, + WMI_LQ_THRESHOLD3_BELOW, + WMI_LQ_THRESHOLD4_ABOVE, + WMI_LQ_THRESHOLD4_BELOW +} WMI_LQ_THRESHOLD_VAL; + +typedef PREPACK struct { + s32 lq; + u8 range; /* WMI_LQ_THRESHOLD_VAL */ +}POSTPACK WMI_LQ_THRESHOLD_EVENT; +/* + * WMI_REPORT_ROAM_TBL_EVENTID + */ +#define MAX_ROAM_TBL_CAND 5 + +typedef PREPACK struct { + s32 roam_util; + u8 bssid[ATH_MAC_LEN]; + s8 rssi; + s8 rssidt; + s8 last_rssi; + s8 util; + s8 bias; + u8 reserved; /* For alignment */ +} POSTPACK WMI_BSS_ROAM_INFO; + + +typedef PREPACK struct { + u16 roamMode; + u16 numEntries; + WMI_BSS_ROAM_INFO bssRoamInfo[1]; +} POSTPACK WMI_TARGET_ROAM_TBL; + +/* + * WMI_HCI_EVENT_EVENTID + */ +typedef PREPACK struct { + u16 evt_buf_sz; /* HCI event buffer size */ + u8 buf[1]; /* HCI event */ +} POSTPACK WMI_HCI_EVENT; + +/* + * WMI_CAC_EVENTID + */ +typedef enum { + CAC_INDICATION_ADMISSION = 0x00, + CAC_INDICATION_ADMISSION_RESP = 0x01, + CAC_INDICATION_DELETE = 0x02, + CAC_INDICATION_NO_RESP = 0x03, +}CAC_INDICATION; + +#define WMM_TSPEC_IE_LEN 63 + +typedef PREPACK struct { + u8 ac; + u8 cac_indication; + u8 statusCode; + u8 tspecSuggestion[WMM_TSPEC_IE_LEN]; +}POSTPACK WMI_CAC_EVENT; + +/* + * WMI_APLIST_EVENTID + */ + +typedef enum { + APLIST_VER1 = 1, +} APLIST_VER; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u16 channel; +} POSTPACK WMI_AP_INFO_V1; + +typedef PREPACK union { + WMI_AP_INFO_V1 apInfoV1; +} POSTPACK WMI_AP_INFO; + +typedef PREPACK struct { + u8 apListVer; + u8 numAP; + WMI_AP_INFO apList[1]; +} POSTPACK WMI_APLIST_EVENT; + +/* + * developer commands + */ + +/* + * WMI_SET_BITRATE_CMDID + * + * Get bit rate cmd uses same definition as set bit rate cmd + */ +typedef enum { + RATE_AUTO = -1, + RATE_1Mb = 0, + RATE_2Mb = 1, + RATE_5_5Mb = 2, + RATE_11Mb = 3, + RATE_6Mb = 4, + RATE_9Mb = 5, + RATE_12Mb = 6, + RATE_18Mb = 7, + RATE_24Mb = 8, + RATE_36Mb = 9, + RATE_48Mb = 10, + RATE_54Mb = 11, + RATE_MCS_0_20 = 12, + RATE_MCS_1_20 = 13, + RATE_MCS_2_20 = 14, + RATE_MCS_3_20 = 15, + RATE_MCS_4_20 = 16, + RATE_MCS_5_20 = 17, + RATE_MCS_6_20 = 18, + RATE_MCS_7_20 = 19, + RATE_MCS_0_40 = 20, + RATE_MCS_1_40 = 21, + RATE_MCS_2_40 = 22, + RATE_MCS_3_40 = 23, + RATE_MCS_4_40 = 24, + RATE_MCS_5_40 = 25, + RATE_MCS_6_40 = 26, + RATE_MCS_7_40 = 27, +} WMI_BIT_RATE; + +typedef PREPACK struct { + s8 rateIndex; /* see WMI_BIT_RATE */ + s8 mgmtRateIndex; + s8 ctlRateIndex; +} POSTPACK WMI_BIT_RATE_CMD; + + +typedef PREPACK struct { + s8 rateIndex; /* see WMI_BIT_RATE */ +} POSTPACK WMI_BIT_RATE_REPLY; + + +/* + * WMI_SET_FIXRATES_CMDID + * + * Get fix rates cmd uses same definition as set fix rates cmd + */ +#define FIX_RATE_1Mb ((u32)0x1) +#define FIX_RATE_2Mb ((u32)0x2) +#define FIX_RATE_5_5Mb ((u32)0x4) +#define FIX_RATE_11Mb ((u32)0x8) +#define FIX_RATE_6Mb ((u32)0x10) +#define FIX_RATE_9Mb ((u32)0x20) +#define FIX_RATE_12Mb ((u32)0x40) +#define FIX_RATE_18Mb ((u32)0x80) +#define FIX_RATE_24Mb ((u32)0x100) +#define FIX_RATE_36Mb ((u32)0x200) +#define FIX_RATE_48Mb ((u32)0x400) +#define FIX_RATE_54Mb ((u32)0x800) +#define FIX_RATE_MCS_0_20 ((u32)0x1000) +#define FIX_RATE_MCS_1_20 ((u32)0x2000) +#define FIX_RATE_MCS_2_20 ((u32)0x4000) +#define FIX_RATE_MCS_3_20 ((u32)0x8000) +#define FIX_RATE_MCS_4_20 ((u32)0x10000) +#define FIX_RATE_MCS_5_20 ((u32)0x20000) +#define FIX_RATE_MCS_6_20 ((u32)0x40000) +#define FIX_RATE_MCS_7_20 ((u32)0x80000) +#define FIX_RATE_MCS_0_40 ((u32)0x100000) +#define FIX_RATE_MCS_1_40 ((u32)0x200000) +#define FIX_RATE_MCS_2_40 ((u32)0x400000) +#define FIX_RATE_MCS_3_40 ((u32)0x800000) +#define FIX_RATE_MCS_4_40 ((u32)0x1000000) +#define FIX_RATE_MCS_5_40 ((u32)0x2000000) +#define FIX_RATE_MCS_6_40 ((u32)0x4000000) +#define FIX_RATE_MCS_7_40 ((u32)0x8000000) + +typedef PREPACK struct { + u32 fixRateMask; /* see WMI_BIT_RATE */ +} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY; + +typedef PREPACK struct { + u8 bEnableMask; + u8 frameType; /*type and subtype*/ + u32 frameRateMask; /* see WMI_BIT_RATE */ +} POSTPACK WMI_FRAME_RATES_CMD, WMI_FRAME_RATES_REPLY; + +/* + * WMI_SET_RECONNECT_AUTH_MODE_CMDID + * + * Set authentication mode + */ +typedef enum { + RECONN_DO_AUTH = 0x00, + RECONN_NOT_AUTH = 0x01 +} WMI_AUTH_MODE; + +typedef PREPACK struct { + u8 mode; +} POSTPACK WMI_SET_AUTH_MODE_CMD; + +/* + * WMI_SET_REASSOC_MODE_CMDID + * + * Set authentication mode + */ +typedef enum { + REASSOC_DO_DISASSOC = 0x00, + REASSOC_DONOT_DISASSOC = 0x01 +} WMI_REASSOC_MODE; + +typedef PREPACK struct { + u8 mode; +}POSTPACK WMI_SET_REASSOC_MODE_CMD; + +typedef enum { + ROAM_DATA_TIME = 1, /* Get The Roam Time Data */ +} ROAM_DATA_TYPE; + +typedef PREPACK struct { + u32 disassoc_time; + u32 no_txrx_time; + u32 assoc_time; + u32 allow_txrx_time; + u8 disassoc_bssid[ATH_MAC_LEN]; + s8 disassoc_bss_rssi; + u8 assoc_bssid[ATH_MAC_LEN]; + s8 assoc_bss_rssi; +} POSTPACK WMI_TARGET_ROAM_TIME; + +typedef PREPACK struct { + PREPACK union { + WMI_TARGET_ROAM_TIME roamTime; + } POSTPACK u; + u8 roamDataType ; +} POSTPACK WMI_TARGET_ROAM_DATA; + +typedef enum { + WMI_WMM_DISABLED = 0, + WMI_WMM_ENABLED +} WMI_WMM_STATUS; + +typedef PREPACK struct { + u8 status; +}POSTPACK WMI_SET_WMM_CMD; + +typedef PREPACK struct { + u8 status; +}POSTPACK WMI_SET_QOS_SUPP_CMD; + +typedef enum { + WMI_TXOP_DISABLED = 0, + WMI_TXOP_ENABLED +} WMI_TXOP_CFG; + +typedef PREPACK struct { + u8 txopEnable; +}POSTPACK WMI_SET_WMM_TXOP_CMD; + +typedef PREPACK struct { + u8 keepaliveInterval; +} POSTPACK WMI_SET_KEEPALIVE_CMD; + +typedef PREPACK struct { + u32 configured; + u8 keepaliveInterval; +} POSTPACK WMI_GET_KEEPALIVE_CMD; + +/* + * Add Application specified IE to a management frame + */ +#define WMI_MAX_IE_LEN 255 + +typedef PREPACK struct { + u8 mgmtFrmType; /* one of WMI_MGMT_FRAME_TYPE */ + u8 ieLen; /* Length of the IE that should be added to the MGMT frame */ + u8 ieInfo[1]; +} POSTPACK WMI_SET_APPIE_CMD; + +/* + * Notify the WSC registration status to the target + */ +#define WSC_REG_ACTIVE 1 +#define WSC_REG_INACTIVE 0 +/* Generic Hal Interface for setting hal paramters. */ +/* Add new Set HAL Param cmdIds here for newer params */ +typedef enum { + WHAL_SETCABTO_CMDID = 1, +}WHAL_CMDID; + +typedef PREPACK struct { + u8 cabTimeOut; +} POSTPACK WHAL_SETCABTO_PARAM; + +typedef PREPACK struct { + u8 whalCmdId; + u8 data[1]; +} POSTPACK WHAL_PARAMCMD; + + +#define WOW_MAX_FILTER_LISTS 1 /*4*/ +#define WOW_MAX_FILTERS_PER_LIST 4 +#define WOW_PATTERN_SIZE 64 +#define WOW_MASK_SIZE 64 + +#define MAC_MAX_FILTERS_PER_LIST 4 + +typedef PREPACK struct { + u8 wow_valid_filter; + u8 wow_filter_id; + u8 wow_filter_size; + u8 wow_filter_offset; + u8 wow_filter_mask[WOW_MASK_SIZE]; + u8 wow_filter_pattern[WOW_PATTERN_SIZE]; +} POSTPACK WOW_FILTER; + + +typedef PREPACK struct { + u8 wow_valid_list; + u8 wow_list_id; + u8 wow_num_filters; + u8 wow_total_list_size; + WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST]; +} POSTPACK WOW_FILTER_LIST; + +typedef PREPACK struct { + u8 valid_filter; + u8 mac_addr[ATH_MAC_LEN]; +} POSTPACK MAC_FILTER; + + +typedef PREPACK struct { + u8 total_list_size; + u8 enable; + MAC_FILTER list[MAC_MAX_FILTERS_PER_LIST]; +} POSTPACK MAC_FILTER_LIST; + +#define MAX_IP_ADDRS 2 +typedef PREPACK struct { + u32 ips[MAX_IP_ADDRS]; /* IP in Network Byte Order */ +} POSTPACK WMI_SET_IP_CMD; + +typedef PREPACK struct { + u32 awake; + u32 asleep; +} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD; + +typedef enum { + WOW_FILTER_SSID = 0x1 +} WMI_WOW_FILTER; + +typedef PREPACK struct { + u32 enable_wow; + WMI_WOW_FILTER filter; + u16 hostReqDelay; +} POSTPACK WMI_SET_WOW_MODE_CMD; + +typedef PREPACK struct { + u8 filter_list_id; +} POSTPACK WMI_GET_WOW_LIST_CMD; + +/* + * WMI_GET_WOW_LIST_CMD reply + */ +typedef PREPACK struct { + u8 num_filters; /* number of patterns in reply */ + u8 this_filter_num; /* this is filter # x of total num_filters */ + u8 wow_mode; + u8 host_mode; + WOW_FILTER wow_filters[1]; +} POSTPACK WMI_GET_WOW_LIST_REPLY; + +typedef PREPACK struct { + u8 filter_list_id; + u8 filter_size; + u8 filter_offset; + u8 filter[1]; +} POSTPACK WMI_ADD_WOW_PATTERN_CMD; + +typedef PREPACK struct { + u16 filter_list_id; + u16 filter_id; +} POSTPACK WMI_DEL_WOW_PATTERN_CMD; + +typedef PREPACK struct { + u8 macaddr[ATH_MAC_LEN]; +} POSTPACK WMI_SET_MAC_ADDRESS_CMD; + +/* + * WMI_SET_AKMP_PARAMS_CMD + */ + +#define WMI_AKMP_MULTI_PMKID_EN 0x000001 + +typedef PREPACK struct { + u32 akmpInfo; +} POSTPACK WMI_SET_AKMP_PARAMS_CMD; + +typedef PREPACK struct { + u8 pmkid[WMI_PMKID_LEN]; +} POSTPACK WMI_PMKID; + +/* + * WMI_SET_PMKID_LIST_CMD + */ +#define WMI_MAX_PMKID_CACHE 8 + +typedef PREPACK struct { + u32 numPMKID; + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; +} POSTPACK WMI_SET_PMKID_LIST_CMD; + +/* + * WMI_GET_PMKID_LIST_CMD Reply + * Following the Number of PMKIDs is the list of PMKIDs + */ +typedef PREPACK struct { + u32 numPMKID; + u8 bssidList[ATH_MAC_LEN][1]; + WMI_PMKID pmkidList[1]; +} POSTPACK WMI_PMKID_LIST_REPLY; + +typedef PREPACK struct { + u16 oldChannel; + u32 newChannel; +} POSTPACK WMI_CHANNEL_CHANGE_EVENT; + +typedef PREPACK struct { + u32 version; +} POSTPACK WMI_WLAN_VERSION_EVENT; + + +/* WMI_ADDBA_REQ_EVENTID */ +typedef PREPACK struct { + u8 tid; + u8 win_sz; + u16 st_seq_no; + u8 status; /* f/w response for ADDBA Req; OK(0) or failure(!=0) */ +} POSTPACK WMI_ADDBA_REQ_EVENT; + +/* WMI_ADDBA_RESP_EVENTID */ +typedef PREPACK struct { + u8 tid; + u8 status; /* OK(0), failure (!=0) */ + u16 amsdu_sz; /* Three values: Not supported(0), 3839, 8k */ +} POSTPACK WMI_ADDBA_RESP_EVENT; + +/* WMI_DELBA_EVENTID + * f/w received a DELBA for peer and processed it. + * Host is notified of this + */ +typedef PREPACK struct { + u8 tid; + u8 is_peer_initiator; + u16 reason_code; +} POSTPACK WMI_DELBA_EVENT; + + +#ifdef WAPI_ENABLE +#define WAPI_REKEY_UCAST 1 +#define WAPI_REKEY_MCAST 2 +typedef PREPACK struct { + u8 type; + u8 macAddr[ATH_MAC_LEN]; +} POSTPACK WMI_WAPIREKEY_EVENT; +#endif + + +/* WMI_ALLOW_AGGR_CMDID + * Configures tid's to allow ADDBA negotiations + * on each tid, in each direction + */ +typedef PREPACK struct { + u16 tx_allow_aggr; /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/ + u16 rx_allow_aggr; /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/ +} POSTPACK WMI_ALLOW_AGGR_CMD; + +/* WMI_ADDBA_REQ_CMDID + * f/w starts performing ADDBA negotiations with peer + * on the given tid + */ +typedef PREPACK struct { + u8 tid; +} POSTPACK WMI_ADDBA_REQ_CMD; + +/* WMI_DELBA_REQ_CMDID + * f/w would teardown BA with peer. + * is_send_initiator indicates if it's or tx or rx side + */ +typedef PREPACK struct { + u8 tid; + u8 is_sender_initiator; + +} POSTPACK WMI_DELBA_REQ_CMD; + +#define PEER_NODE_JOIN_EVENT 0x00 +#define PEER_NODE_LEAVE_EVENT 0x01 +#define PEER_FIRST_NODE_JOIN_EVENT 0x10 +#define PEER_LAST_NODE_LEAVE_EVENT 0x11 +typedef PREPACK struct { + u8 eventCode; + u8 peerMacAddr[ATH_MAC_LEN]; +} POSTPACK WMI_PEER_NODE_EVENT; + +#define IEEE80211_FRAME_TYPE_MGT 0x00 +#define IEEE80211_FRAME_TYPE_CTL 0x04 + +/* + * Transmit complete event data structure(s) + */ + + +typedef PREPACK struct { +#define TX_COMPLETE_STATUS_SUCCESS 0 +#define TX_COMPLETE_STATUS_RETRIES 1 +#define TX_COMPLETE_STATUS_NOLINK 2 +#define TX_COMPLETE_STATUS_TIMEOUT 3 +#define TX_COMPLETE_STATUS_OTHER 4 + + u8 status; /* one of TX_COMPLETE_STATUS_... */ + u8 pktID; /* packet ID to identify parent packet */ + u8 rateIdx; /* rate index on successful transmission */ + u8 ackFailures; /* number of ACK failures in tx attempt */ +#if 0 /* optional params currently omitted. */ + u32 queueDelay; // usec delay measured Tx Start time - host delivery time + u32 mediaDelay; // usec delay measured ACK rx time - host delivery time +#endif +} POSTPACK TX_COMPLETE_MSG_V1; /* version 1 of tx complete msg */ + +typedef PREPACK struct { + u8 numMessages; /* number of tx comp msgs following this struct */ + u8 msgLen; /* length in bytes for each individual msg following this struct */ + u8 msgType; /* version of tx complete msg data following this struct */ + u8 reserved; /* individual messages follow this header */ +} POSTPACK WMI_TX_COMPLETE_EVENT; + +#define WMI_TXCOMPLETE_VERSION_1 (0x01) + + +/* + * ------- AP Mode definitions -------------- + */ + +/* + * !!! Warning !!! + * -Changing the following values needs compilation of both driver and firmware + */ +#ifdef AR6002_REV2 +#define AP_MAX_NUM_STA 4 +#else +#define AP_MAX_NUM_STA 8 +#endif +#define AP_ACL_SIZE 10 +#define IEEE80211_MAX_IE 256 +#define MCAST_AID 0xFF /* Spl. AID used to set DTIM flag in the beacons */ +#define DEF_AP_COUNTRY_CODE "US " +#define DEF_AP_WMODE_G WMI_11G_MODE +#define DEF_AP_WMODE_AG WMI_11AG_MODE +#define DEF_AP_DTIM 5 +#define DEF_BEACON_INTERVAL 100 + +/* AP mode disconnect reasons */ +#define AP_DISCONNECT_STA_LEFT 101 +#define AP_DISCONNECT_FROM_HOST 102 +#define AP_DISCONNECT_COMM_TIMEOUT 103 + +/* + * Used with WMI_AP_HIDDEN_SSID_CMDID + */ +#define HIDDEN_SSID_FALSE 0 +#define HIDDEN_SSID_TRUE 1 +typedef PREPACK struct { + u8 hidden_ssid; +} POSTPACK WMI_AP_HIDDEN_SSID_CMD; + +/* + * Used with WMI_AP_ACL_POLICY_CMDID + */ +#define AP_ACL_DISABLE 0x00 +#define AP_ACL_ALLOW_MAC 0x01 +#define AP_ACL_DENY_MAC 0x02 +#define AP_ACL_RETAIN_LIST_MASK 0x80 +typedef PREPACK struct { + u8 policy; +} POSTPACK WMI_AP_ACL_POLICY_CMD; + +/* + * Used with WMI_AP_ACL_MAC_LIST_CMDID + */ +#define ADD_MAC_ADDR 1 +#define DEL_MAC_ADDR 2 +typedef PREPACK struct { + u8 action; + u8 index; + u8 mac[ATH_MAC_LEN]; + u8 wildcard; +} POSTPACK WMI_AP_ACL_MAC_CMD; + +typedef PREPACK struct { + u16 index; + u8 acl_mac[AP_ACL_SIZE][ATH_MAC_LEN]; + u8 wildcard[AP_ACL_SIZE]; + u8 policy; +} POSTPACK WMI_AP_ACL; + +/* + * Used with WMI_AP_SET_NUM_STA_CMDID + */ +typedef PREPACK struct { + u8 num_sta; +} POSTPACK WMI_AP_SET_NUM_STA_CMD; + +/* + * Used with WMI_AP_SET_MLME_CMDID + */ +typedef PREPACK struct { + u8 mac[ATH_MAC_LEN]; + u16 reason; /* 802.11 reason code */ + u8 cmd; /* operation to perform */ +#define WMI_AP_MLME_ASSOC 1 /* associate station */ +#define WMI_AP_DISASSOC 2 /* disassociate station */ +#define WMI_AP_DEAUTH 3 /* deauthenticate station */ +#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */ +#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */ +} POSTPACK WMI_AP_SET_MLME_CMD; + +typedef PREPACK struct { + u32 period; +} POSTPACK WMI_AP_CONN_INACT_CMD; + +typedef PREPACK struct { + u32 period_min; + u32 dwell_ms; +} POSTPACK WMI_AP_PROT_SCAN_TIME_CMD; + +typedef PREPACK struct { + u32 flag; + u16 aid; +} POSTPACK WMI_AP_SET_PVB_CMD; + +#define WMI_DISABLE_REGULATORY_CODE "FF" + +typedef PREPACK struct { + u8 countryCode[3]; +} POSTPACK WMI_AP_SET_COUNTRY_CMD; + +typedef PREPACK struct { + u8 dtim; +} POSTPACK WMI_AP_SET_DTIM_CMD; + +typedef PREPACK struct { + u8 band; /* specifies which band to apply these values */ + u8 enable; /* allows 11n to be disabled on a per band basis */ + u8 chan_width_40M_supported; + u8 short_GI_20MHz; + u8 short_GI_40MHz; + u8 intolerance_40MHz; + u8 max_ampdu_len_exp; +} POSTPACK WMI_SET_HT_CAP_CMD; + +typedef PREPACK struct { + u8 sta_chan_width; +} POSTPACK WMI_SET_HT_OP_CMD; + +typedef PREPACK struct { + u32 rateMasks[8]; +} POSTPACK WMI_SET_TX_SELECT_RATES_CMD; + +typedef PREPACK struct { + u32 sgiMask; + u8 sgiPERThreshold; +} POSTPACK WMI_SET_TX_SGI_PARAM_CMD; + +#define DEFAULT_SGI_MASK 0x08080000 +#define DEFAULT_SGI_PER 10 + +typedef PREPACK struct { + u32 rateField; /* 1 bit per rate corresponding to index */ + u8 id; + u8 shortTrys; + u8 longTrys; + u8 reserved; /* padding */ +} POSTPACK WMI_SET_RATE_POLICY_CMD; + +typedef PREPACK struct { + u8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */ + u8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 */ + u8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target */ + u8 reserved[1]; /* alignment */ +} POSTPACK WMI_RX_FRAME_FORMAT_CMD; + + +typedef PREPACK struct { + u8 enable; /* 1 == device operates in thin mode , 0 == normal mode */ + u8 reserved[3]; +} POSTPACK WMI_SET_THIN_MODE_CMD; + +/* AP mode events */ +/* WMI_PS_POLL_EVENT */ +typedef PREPACK struct { + u16 aid; +} POSTPACK WMI_PSPOLL_EVENT; + +typedef PREPACK struct { + u32 tx_bytes; + u32 tx_pkts; + u32 tx_error; + u32 tx_discard; + u32 rx_bytes; + u32 rx_pkts; + u32 rx_error; + u32 rx_discard; + u32 aid; +} POSTPACK WMI_PER_STA_STAT; + +#define AP_GET_STATS 0 +#define AP_CLEAR_STATS 1 + +typedef PREPACK struct { + u32 action; + WMI_PER_STA_STAT sta[AP_MAX_NUM_STA+1]; +} POSTPACK WMI_AP_MODE_STAT; +#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(u32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT))) + +#define AP_11BG_RATESET1 1 +#define AP_11BG_RATESET2 2 +#define DEF_AP_11BG_RATESET AP_11BG_RATESET1 +typedef PREPACK struct { + u8 rateset; +} POSTPACK WMI_AP_SET_11BG_RATESET_CMD; +/* + * End of AP mode definitions + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/wmix.h b/trunk/drivers/staging/ath6kl/include/common/wmix.h new file mode 100644 index 000000000000..9435eab1b7f5 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wmix.h @@ -0,0 +1,271 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* + * This file contains extensions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all + * extended commands and events. Extensions include useful commands + * that are not directly related to wireless activities. They may + * be hardware-specific, and they might not be supported on all + * implementations. + * + * Extended WMIX commands are encapsulated in a WMI message with + * cmd=WMI_EXTENSION_CMD. + */ + +#ifndef _WMIX_H_ +#define _WMIX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog.h" + +/* + * Extended WMI commands are those that are needed during wireless + * operation, but which are not really wireless commands. This allows, + * for instance, platform-specific commands. Extended WMI commands are + * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID. + * Extended WMI events are similarly embedded in a WMI event message with + * WMI_EVENT_ID=WMI_EXTENSION_EVENTID. + */ +typedef PREPACK struct { + u32 commandId; +} POSTPACK WMIX_CMD_HDR; + +typedef enum { + WMIX_DSETOPEN_REPLY_CMDID = 0x2001, + WMIX_DSETDATA_REPLY_CMDID, + WMIX_GPIO_OUTPUT_SET_CMDID, + WMIX_GPIO_INPUT_GET_CMDID, + WMIX_GPIO_REGISTER_SET_CMDID, + WMIX_GPIO_REGISTER_GET_CMDID, + WMIX_GPIO_INTR_ACK_CMDID, + WMIX_HB_CHALLENGE_RESP_CMDID, + WMIX_DBGLOG_CFG_MODULE_CMDID, + WMIX_PROF_CFG_CMDID, /* 0x200a */ + WMIX_PROF_ADDR_SET_CMDID, + WMIX_PROF_START_CMDID, + WMIX_PROF_STOP_CMDID, + WMIX_PROF_COUNT_GET_CMDID, +} WMIX_COMMAND_ID; + +typedef enum { + WMIX_DSETOPENREQ_EVENTID = 0x3001, + WMIX_DSETCLOSE_EVENTID, + WMIX_DSETDATAREQ_EVENTID, + WMIX_GPIO_INTR_EVENTID, + WMIX_GPIO_DATA_EVENTID, + WMIX_GPIO_ACK_EVENTID, + WMIX_HB_CHALLENGE_RESP_EVENTID, + WMIX_DBGLOG_EVENTID, + WMIX_PROF_COUNT_EVENTID, +} WMIX_EVENT_ID; + +/* + * =============DataSet support================= + */ + +/* + * WMIX_DSETOPENREQ_EVENTID + * DataSet Open Request Event + */ +typedef PREPACK struct { + u32 dset_id; + u32 targ_dset_handle; /* echo'ed, not used by Host, */ + u32 targ_reply_fn; /* echo'ed, not used by Host, */ + u32 targ_reply_arg; /* echo'ed, not used by Host, */ +} POSTPACK WMIX_DSETOPENREQ_EVENT; + +/* + * WMIX_DSETCLOSE_EVENTID + * DataSet Close Event + */ +typedef PREPACK struct { + u32 access_cookie; +} POSTPACK WMIX_DSETCLOSE_EVENT; + +/* + * WMIX_DSETDATAREQ_EVENTID + * DataSet Data Request Event + */ +typedef PREPACK struct { + u32 access_cookie; + u32 offset; + u32 length; + u32 targ_buf; /* echo'ed, not used by Host, */ + u32 targ_reply_fn; /* echo'ed, not used by Host, */ + u32 targ_reply_arg; /* echo'ed, not used by Host, */ +} POSTPACK WMIX_DSETDATAREQ_EVENT; + +typedef PREPACK struct { + u32 status; + u32 targ_dset_handle; + u32 targ_reply_fn; + u32 targ_reply_arg; + u32 access_cookie; + u32 size; + u32 version; +} POSTPACK WMIX_DSETOPEN_REPLY_CMD; + +typedef PREPACK struct { + u32 status; + u32 targ_buf; + u32 targ_reply_fn; + u32 targ_reply_arg; + u32 length; + u8 buf[1]; +} POSTPACK WMIX_DSETDATA_REPLY_CMD; + + +/* + * =============GPIO support================= + * All masks are 18-bit masks with bit N operating on GPIO pin N. + */ + + +/* + * Set GPIO pin output state. + * In order for output to be driven, a pin must be enabled for output. + * This can be done during initialization through the GPIO Configuration + * DataSet, or during operation with the enable_mask. + * + * If a request is made to simultaneously set/clear or set/disable or + * clear/disable or disable/enable, results are undefined. + */ +typedef PREPACK struct { + u32 set_mask; /* pins to set */ + u32 clear_mask; /* pins to clear */ + u32 enable_mask; /* pins to enable for output */ + u32 disable_mask; /* pins to disable/tristate */ +} POSTPACK WMIX_GPIO_OUTPUT_SET_CMD; + +/* + * Set a GPIO register. For debug/exceptional cases. + * Values for gpioreg_id are GPIO_REGISTER_IDs, defined in a + * platform-dependent header. + */ +typedef PREPACK struct { + u32 gpioreg_id; /* GPIO register ID */ + u32 value; /* value to write */ +} POSTPACK WMIX_GPIO_REGISTER_SET_CMD; + +/* Get a GPIO register. For debug/exceptional cases. */ +typedef PREPACK struct { + u32 gpioreg_id; /* GPIO register to read */ +} POSTPACK WMIX_GPIO_REGISTER_GET_CMD; + +/* + * Host acknowledges and re-arms GPIO interrupts. A single + * message should be used to acknowledge all interrupts that + * were delivered in an earlier WMIX_GPIO_INTR_EVENT message. + */ +typedef PREPACK struct { + u32 ack_mask; /* interrupts to acknowledge */ +} POSTPACK WMIX_GPIO_INTR_ACK_CMD; + +/* + * Target informs Host of GPIO interrupts that have occurred since the + * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information -- + * the current GPIO input values is provided -- in order to support + * use of a GPIO interrupt as a Data Valid signal for other GPIO pins. + */ +typedef PREPACK struct { + u32 intr_mask; /* pending GPIO interrupts */ + u32 input_values; /* recent GPIO input values */ +} POSTPACK WMIX_GPIO_INTR_EVENT; + +/* + * Target responds to Host's earlier WMIX_GPIO_INPUT_GET_CMDID request + * using a GPIO_DATA_EVENT with + * value set to the mask of GPIO pin inputs and + * reg_id set to GPIO_ID_NONE + * + * + * Target responds to Hosts's earlier WMIX_GPIO_REGISTER_GET_CMDID request + * using a GPIO_DATA_EVENT with + * value set to the value of the requested register and + * reg_id identifying the register (reflects the original request) + * NB: reg_id supports the future possibility of unsolicited + * WMIX_GPIO_DATA_EVENTs (for polling GPIO input), and it may + * simplify Host GPIO support. + */ +typedef PREPACK struct { + u32 value; + u32 reg_id; +} POSTPACK WMIX_GPIO_DATA_EVENT; + +/* + * =============Error Detection support================= + */ + +/* + * WMIX_HB_CHALLENGE_RESP_CMDID + * Heartbeat Challenge Response command + */ +typedef PREPACK struct { + u32 cookie; + u32 source; +} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD; + +/* + * WMIX_HB_CHALLENGE_RESP_EVENTID + * Heartbeat Challenge Response Event + */ +#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD + +typedef PREPACK struct { + struct dbglog_config_s config; +} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD; + +/* + * =============Target Profiling support================= + */ + +typedef PREPACK struct { + u32 period; /* Time (in 30.5us ticks) between samples */ + u32 nbins; +} POSTPACK WMIX_PROF_CFG_CMD; + +typedef PREPACK struct { + u32 addr; +} POSTPACK WMIX_PROF_ADDR_SET_CMD; + +/* + * Target responds to Hosts's earlier WMIX_PROF_COUNT_GET_CMDID request + * using a WMIX_PROF_COUNT_EVENT with + * addr set to the next address + * count set to the corresponding count + */ +typedef PREPACK struct { + u32 addr; + u32 count; +} POSTPACK WMIX_PROF_COUNT_EVENT; + + +#ifdef __cplusplus +} +#endif + +#endif /* _WMIX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common_drv.h b/trunk/drivers/staging/ath6kl/include/common_drv.h new file mode 100644 index 000000000000..34db29958bcb --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common_drv.h @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef COMMON_DRV_H_ +#define COMMON_DRV_H_ + +#include "hif.h" +#include "htc_packet.h" +#include "htc_api.h" + +/* structure that is the state information for the default credit distribution callback + * drivers should instantiate (zero-init as well) this structure in their driver instance + * and pass it as a context to the HTC credit distribution functions */ +struct common_credit_state_info { + int TotalAvailableCredits; /* total credits in the system at startup */ + int CurrentFreeCredits; /* credits available in the pool that have not been + given out to endpoints */ + struct htc_endpoint_credit_dist *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */ +}; + +struct hci_transport_callbacks { + s32 (*setupTransport)(void *ar); + void (*cleanupTransport)(void *ar); +}; + +struct hci_transport_misc_handles { + void *netDevice; + void *hifDevice; + void *htcHandle; +}; + +/* HTC TX packet tagging definitions */ +#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED +#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1) + +#define AR6002_VERSION_REV1 0x20000086 +#define AR6002_VERSION_REV2 0x20000188 +#define AR6003_VERSION_REV1 0x300002ba +#define AR6003_VERSION_REV2 0x30000384 + +#define AR6002_CUST_DATA_SIZE 112 +#define AR6003_CUST_DATA_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* OS-independent APIs */ +int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo); + +int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, u8 *data, u32 length); + +int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset); + +void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType); + +int ar6000_set_htc_params(struct hif_device *hifDevice, + u32 TargetType, + u32 MboxIsrYieldValue, + u8 HtcControlBuffers); + +int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice, + u32 TargetType, + u32 Flags); + +void ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType); + +u8 *ar6000_get_cust_data_buffer(u32 TargetType); + +int ar6000_setBTState(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setDevicePowerState(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setWowMode(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setHostMode(void *context, u8 *pInBuf, u32 InBufSize); + +#ifdef __cplusplus +} +#endif + +#endif /*COMMON_DRV_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/dbglog_api.h b/trunk/drivers/staging/ath6kl/include/dbglog_api.h new file mode 100644 index 000000000000..a53aed316e3b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dbglog_api.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains host side debug primitives. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _DBGLOG_API_H_ +#define _DBGLOG_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog.h" + +#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE + +#define DBGLOG_GET_DBGID(arg) \ + ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET) + +#define DBGLOG_GET_MODULEID(arg) \ + ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET) + +#define DBGLOG_GET_NUMARGS(arg) \ + ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET) + +#define DBGLOG_GET_TIMESTAMP(arg) \ + ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET) + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/dl_list.h b/trunk/drivers/staging/ath6kl/include/dl_list.h new file mode 100644 index 000000000000..13b1e6956c22 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dl_list.h @@ -0,0 +1,153 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Double-link list definitions (adapted from Atheros SDIO stack) +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef __DL_LIST_H___ +#define __DL_LIST_H___ + +#include "a_osapi.h" + +#define A_CONTAINING_STRUCT(address, struct_type, field_name)\ + ((struct_type *)((unsigned long)(address) - (unsigned long)(&((struct_type *)0)->field_name))) + +/* list functions */ +/* pointers for the list */ +struct dl_list { + struct dl_list *pPrev; + struct dl_list *pNext; +}; +/* + * DL_LIST_INIT , initialize doubly linked list +*/ +#define DL_LIST_INIT(pList)\ + {(pList)->pPrev = pList; (pList)->pNext = pList;} + +/* faster macro to init list and add a single item */ +#define DL_LIST_INIT_AND_ADD(pList,pItem) \ +{ (pList)->pPrev = (pItem); \ + (pList)->pNext = (pItem); \ + (pItem)->pNext = (pList); \ + (pItem)->pPrev = (pList); \ +} + +#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList))) +#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext +#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev +/* + * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member + * NOT: do not use this function if the items in the list are deleted inside the + * iteration loop +*/ +#define ITERATE_OVER_LIST(pStart, pTemp) \ + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext) + + +/* safe iterate macro that allows the item to be removed from the list + * the iteration continues to the next item in the list + */ +#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \ +{ \ + struct dl_list * pTemp; \ + pTemp = (pStart)->pNext; \ + while (pTemp != (pStart)) { \ + (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \ + pTemp = pTemp->pNext; \ + +#define ITERATE_END }} + +/* + * DL_ListInsertTail - insert pAdd to the end of the list +*/ +static INLINE struct dl_list *DL_ListInsertTail(struct dl_list *pList, struct dl_list *pAdd) { + /* insert at tail */ + pAdd->pPrev = pList->pPrev; + pAdd->pNext = pList; + pList->pPrev->pNext = pAdd; + pList->pPrev = pAdd; + return pAdd; +} + +/* + * DL_ListInsertHead - insert pAdd into the head of the list +*/ +static INLINE struct dl_list * DL_ListInsertHead(struct dl_list * pList, struct dl_list * pAdd) { + /* insert at head */ + pAdd->pPrev = pList; + pAdd->pNext = pList->pNext; + pList->pNext->pPrev = pAdd; + pList->pNext = pAdd; + return pAdd; +} + +#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem)) +/* + * DL_ListRemove - remove pDel from list +*/ +static INLINE struct dl_list * DL_ListRemove(struct dl_list * pDel) { + pDel->pNext->pPrev = pDel->pPrev; + pDel->pPrev->pNext = pDel->pNext; + /* point back to itself just to be safe, incase remove is called again */ + pDel->pNext = pDel; + pDel->pPrev = pDel; + return pDel; +} + +/* + * DL_ListRemoveItemFromHead - get a list item from the head +*/ +static INLINE struct dl_list * DL_ListRemoveItemFromHead(struct dl_list * pList) { + struct dl_list * pItem = NULL; + if (pList->pNext != pList) { + pItem = pList->pNext; + /* remove the first item from head */ + DL_ListRemove(pItem); + } + return pItem; +} + +static INLINE struct dl_list * DL_ListRemoveItemFromTail(struct dl_list * pList) { + struct dl_list * pItem = NULL; + if (pList->pPrev != pList) { + pItem = pList->pPrev; + /* remove the item from tail */ + DL_ListRemove(pItem); + } + return pItem; +} + +/* transfer src list items to the tail of the destination list */ +static INLINE void DL_ListTransferItemsToTail(struct dl_list * pDest, struct dl_list * pSrc) { + /* only concatenate if src is not empty */ + if (!DL_LIST_IS_EMPTY(pSrc)) { + /* cut out circular list in src and re-attach to end of dest */ + pSrc->pPrev->pNext = pDest; + pSrc->pNext->pPrev = pDest->pPrev; + pDest->pPrev->pNext = pSrc->pNext; + pDest->pPrev = pSrc->pPrev; + /* terminate src list, it is now empty */ + pSrc->pPrev = pSrc; + pSrc->pNext = pSrc; + } +} + +#endif /* __DL_LIST_H___ */ diff --git a/trunk/drivers/staging/ath6kl/include/dset_api.h b/trunk/drivers/staging/ath6kl/include/dset_api.h new file mode 100644 index 000000000000..fe901ba40ec6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dset_api.h @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Host-side DataSet API. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _DSET_API_H_ +#define _DSET_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Host-side DataSet support is optional, and is not + * currently required for correct operation. To disable + * Host-side DataSet support, set this to 0. + */ +#ifndef CONFIG_HOST_DSET_SUPPORT +#define CONFIG_HOST_DSET_SUPPORT 1 +#endif + +/* Called to send a DataSet Open Reply back to the Target. */ +int wmi_dset_open_reply(struct wmi_t *wmip, + u32 status, + u32 access_cookie, + u32 size, + u32 version, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg); + +/* Called to send a DataSet Data Reply back to the Target. */ +int wmi_dset_data_reply(struct wmi_t *wmip, + u32 status, + u8 *host_buf, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* _DSET_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/hci_transport_api.h b/trunk/drivers/staging/ath6kl/include/hci_transport_api.h new file mode 100644 index 000000000000..5e903fad23fc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/hci_transport_api.h @@ -0,0 +1,259 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HCI_TRANSPORT_API_H_ +#define _HCI_TRANSPORT_API_H_ + + /* Bluetooth HCI packets are stored in HTC packet containers */ +#include "htc_packet.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef void *HCI_TRANSPORT_HANDLE; + +typedef HTC_ENDPOINT_ID HCI_TRANSPORT_PACKET_TYPE; + + /* we map each HCI packet class to a static Endpoint ID */ +#define HCI_COMMAND_TYPE ENDPOINT_1 +#define HCI_EVENT_TYPE ENDPOINT_2 +#define HCI_ACL_TYPE ENDPOINT_3 +#define HCI_PACKET_INVALID ENDPOINT_MAX + +#define HCI_GET_PACKET_TYPE(pP) (pP)->Endpoint +#define HCI_SET_PACKET_TYPE(pP,s) (pP)->Endpoint = (s) + +/* callback when an HCI packet was completely sent */ +typedef void (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, struct htc_packet *); +/* callback when an HCI packet is received */ +typedef void (*HCI_TRANSPORT_RECV_PKT)(void *, struct htc_packet *); +/* Optional receive buffer re-fill callback, + * On some OSes (like Linux) packets are allocated from a global pool and indicated up + * to the network stack. The driver never gets the packets back from the OS. For these OSes + * a refill callback can be used to allocate and re-queue buffers into HTC. + * A refill callback is used for the reception of ACL and EVENT packets. The caller must + * set the watermark trigger point to cause a refill. + */ +typedef void (*HCI_TRANSPORT_RECV_REFILL)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable); +/* Optional receive packet refill + * On some systems packet buffers are an extremely limited resource. Rather than + * queue largest-possible-sized buffers to the HCI bridge, some systems would rather + * allocate a specific size as the packet is received. The trade off is + * slightly more processing (callback invoked for each RX packet) + * for the benefit of committing fewer buffer resources into the bridge. + * + * The callback is provided the length of the pending packet to fetch. This includes the + * full transport header, HCI header, plus the length of payload. The callback can return a pointer to + * the allocated HTC packet for immediate use. + * + * NOTE*** This callback is mutually exclusive with the the refill callback above. + * + * */ +typedef struct htc_packet *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length); + +typedef enum _HCI_SEND_FULL_ACTION { + HCI_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */ + HCI_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */ +} HCI_SEND_FULL_ACTION; + +/* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold, + * the callback must return the send full action to take (either DROP or KEEP) */ +typedef HCI_SEND_FULL_ACTION (*HCI_TRANSPORT_SEND_FULL)(void *, struct htc_packet *); + +struct hci_transport_properties { + int HeadRoom; /* number of bytes in front of HCI packet for header space */ + int TailRoom; /* number of bytes at the end of the HCI packet for tail space */ + int IOBlockPad; /* I/O block padding required (always a power of 2) */ +}; + +struct hci_transport_config_info { + int ACLRecvBufferWaterMark; /* low watermark to trigger recv refill */ + int EventRecvBufferWaterMark; /* low watermark to trigger recv refill */ + int MaxSendQueueDepth; /* max number of packets in the single send queue */ + void *pContext; /* context for all callbacks */ + void (*TransportFailure)(void *pContext, int Status); /* transport failure callback */ + int (*TransportReady)(HCI_TRANSPORT_HANDLE, struct hci_transport_properties *,void *pContext); /* transport is ready */ + void (*TransportRemoved)(void *pContext); /* transport was removed */ + /* packet processing callbacks */ + HCI_TRANSPORT_SEND_PKT_COMPLETE pHCISendComplete; + HCI_TRANSPORT_RECV_PKT pHCIPktRecv; + HCI_TRANSPORT_RECV_REFILL pHCIPktRecvRefill; + HCI_TRANSPORT_RECV_ALLOC pHCIPktRecvAlloc; + HCI_TRANSPORT_SEND_FULL pHCISendFull; +}; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Attach to the HCI transport module + @function name: HCI_TransportAttach + @input: HTCHandle - HTC handle (see HTC apis) + pInfo - initialization information + @output: + @return: HCI_TRANSPORT_HANDLE on success, NULL on failure + @notes: The HTC module provides HCI transport services. + @example: + @see also: HCI_TransportDetach ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Detach from the HCI transport module + @function name: HCI_TransportDetach + @input: HciTrans - HCI transport handle + pInfo - initialization information + @output: + @return: + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packets to the HCI transport + @function name: HCI_TransportAddReceivePkts + @input: HciTrans - HCI transport handle + pQueue - a queue holding one or more packets + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HCI packets. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. Each packet in the queue must be of the same type and length + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HCI packet packet + @function name: HCI_TransportSendPkt + @input: HciTrans - HCI transport handle + pPacket - packet to send + Synchronous - send the packet synchronously (blocking) + @output: + @return: 0 + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and + HCI_SET_PACKET_TYPE() macros to prepare the packet. + If Synchronous is set to false the call is fully asynchronous. On error or completion, + the registered send complete callback will be called. + If Synchronous is set to true, the call will block until the packet is sent, if the + interface cannot send the packet within a 2 second timeout, the function will return + the failure code : A_EBUSY. + + Synchronous Mode should only be used at start-up to initialize the HCI device using + custom HCI commands. It should NOT be mixed with Asynchronous operations. Mixed synchronous + and asynchronous operation behavior is undefined. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HCI transport + @function name: HCI_TransportStop + @input: HciTrans - hci transport handle + @output: + @return: + @notes: HCI transport communication will be halted. All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start the HCI transport + @function name: HCI_TransportStart + @input: HciTrans - hci transport handle + @output: + @return: 0 on success + @notes: HCI transport communication will begin, the caller can expect the arrival + of HCI recv packets as soon as this call returns. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Enable or Disable Asynchronous Recv + @function name: HCI_TransportEnableDisableAsyncRecv + @input: HciTrans - hci transport handle + Enable - enable or disable asynchronous recv + @output: + @return: 0 on success + @notes: This API must be called when HCI recv is handled synchronously + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Receive an event packet from the HCI transport synchronously using polling + @function name: HCI_TransportRecvHCIEventSync + @input: HciTrans - hci transport handle + pPacket - HTC packet to hold the recv data + MaxPollMS - maximum polling duration in Milliseconds; + @output: + @return: 0 on success + @notes: This API should be used only during HCI device initialization, the caller must call + HCI_TransportEnableDisableAsyncRecv with Enable=false prior to using this API. + This API will only capture HCI Event packets. + @example: + @see also: HCI_TransportEnableDisableAsyncRecv ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set the desired baud rate for the underlying transport layer + @function name: HCI_TransportSetBaudRate + @input: HciTrans - hci transport handle + Baud - baud rate in bps + @output: + @return: 0 on success + @notes: This API should be used only after HCI device initialization + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Enable/Disable HCI Transport Power Management + @function name: HCI_TransportEnablePowerMgmt + @input: HciTrans - hci transport handle + Enable - 1 = Enable, 0 = Disable + @output: + @return: 0 on success + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +#ifdef __cplusplus +} +#endif + +#endif /* _HCI_TRANSPORT_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/hif.h b/trunk/drivers/staging/ath6kl/include/hif.h new file mode 100644 index 000000000000..24200e778c3b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/hif.h @@ -0,0 +1,456 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF specific declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_H_ +#define _HIF_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "dl_list.h" + + +typedef struct htc_callbacks HTC_CALLBACKS; +struct hif_device; + +/* + * direction - Direction of transfer (HIF_READ/HIF_WRITE). + */ +#define HIF_READ 0x00000001 +#define HIF_WRITE 0x00000002 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE) + +/* + * type - An interface may support different kind of read/write commands. + * For example: SDIO supports CMD52/CMD53s. In case of MSIO it + * translates to using different kinds of TPCs. The command type + * is thus divided into a basic and an extended command and can + * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO. + */ +#define HIF_BASIC_IO 0x00000004 +#define HIF_EXTENDED_IO 0x00000008 +#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO) + +/* + * emode - This indicates the whether the command is to be executed in a + * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ + * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been + * implemented using the asynchronous mode allowing the the bus + * driver to indicate the completion of operation through the + * registered callback routine. The requirement primarily comes + * from the contexts these operations get called from (a driver's + * transmit context or the ISR context in case of receive). + * Support for both of these modes is essential. + */ +#define HIF_SYNCHRONOUS 0x00000010 +#define HIF_ASYNCHRONOUS 0x00000020 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) + +/* + * dmode - An interface may support different kinds of commands based on + * the tradeoff between the amount of data it can carry and the + * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ + * HIF_BLOCK_BASIS). In case of latter, the data is rounded off + * to the nearest block size by padding. The size of the block is + * configurable at compile time using the HIF_BLOCK_SIZE and is + * negotiated with the target during initialization after the + * AR6000 interrupts are enabled. + */ +#define HIF_BYTE_BASIS 0x00000040 +#define HIF_BLOCK_BASIS 0x00000080 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) + +/* + * amode - This indicates if the address has to be incremented on AR6000 + * after every read/write operation (HIF?FIXED_ADDRESS/ + * HIF_INCREMENTAL_ADDRESS). + */ +#define HIF_FIXED_ADDRESS 0x00000100 +#define HIF_INCREMENTAL_ADDRESS 0x00000200 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_ASYNC_BYTE_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_ASYNC_BYTE_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BYTE_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BYTE_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BLOCK_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_SYNC_BYTE_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BYTE_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) + +typedef enum { + HIF_DEVICE_POWER_STATE = 0, + HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + HIF_DEVICE_GET_MBOX_ADDR, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + HIF_DEVICE_GET_IRQ_PROC_MODE, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + HIF_DEVICE_POWER_STATE_CHANGE, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, + HIF_DEVICE_GET_OS_DEVICE, + HIF_DEVICE_DEBUG_BUS_STATE, +} HIF_DEVICE_CONFIG_OPCODE; + +/* + * HIF CONFIGURE definitions: + * + * HIF_DEVICE_GET_MBOX_BLOCK_SIZE + * input : none + * output : array of 4 u32s + * notes: block size is returned for each mailbox (4) + * + * HIF_DEVICE_GET_MBOX_ADDR + * input : none + * output : struct hif_device_mbox_info + * notes: + * + * HIF_DEVICE_GET_PENDING_EVENTS_FUNC + * input : none + * output: HIF_PENDING_EVENTS_FUNC function pointer + * notes: this is optional for the HIF layer, if the request is + * not handled then it indicates that the upper layer can use + * the standard device methods to get pending events (IRQs, mailbox messages etc..) + * otherwise it can call the function pointer to check pending events. + * + * HIF_DEVICE_GET_IRQ_PROC_MODE + * input : none + * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode) + * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF + * layer can report whether IRQ processing is requires synchronous behavior or + * can be processed using asynchronous bus requests (typically faster). + * + * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC + * input : + * output : HIF_MASK_UNMASK_RECV_EVENT function pointer + * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism + * to mask receive message events. The upper layer can call this pointer when it needs + * to mask/unmask receive events (in case it runs out of buffers). + * + * HIF_DEVICE_POWER_STATE_CHANGE + * + * input : HIF_DEVICE_POWER_CHANGE_TYPE + * output : none + * note: this is optional for the HIF layer. The HIF layer can handle power on/off state change + * requests in an interconnect specific way. This is highly OS and bus driver dependent. + * The caller must guarantee that no HIF read/write requests will be made after the device + * is powered down. + * + * HIF_DEVICE_GET_IRQ_YIELD_PARAMS + * + * input : none + * output : struct hif_device_irq_yield_params + * note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler. + * The DSR callback handler will exit after a fixed number of RX packets or events are processed. + * This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. + * The HIF implementation can ignore this command if it does not desire the DSR callback to yield. + * The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the + * DSR handler callback must yield and return control back to the HIF layer. When a yield limit is + * used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning. + * The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared + * to process interrupts again. + * + * HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT + * input : none + * output : struct hif_device_scatter_support_info + * note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests + * allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for + * multi-message transfers that can better utilize the bus interconnect. + * + * + * HIF_DEVICE_GET_OS_DEVICE + * intput : none + * output : struct hif_device_os_device_info; + * note: On some operating systems, the HIF layer has a parent device object for the bus. This object + * may be required to register certain types of logical devices. + * + * HIF_DEVICE_DEBUG_BUS_STATE + * input : none + * output : none + * note: This configure option triggers the HIF interface to dump as much bus interface state. This + * configuration request is optional (No-OP on some HIF implementations) + * + */ + +struct hif_mbox_properties { + u32 ExtendedAddress; /* extended address for larger writes */ + u32 ExtendedSize; +}; + +#define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */ + +typedef enum _MBOX_BUF_IF_TYPE { + MBOX_BUS_IF_SDIO = 0, + MBOX_BUS_IF_SPI = 1, +} MBOX_BUF_IF_TYPE; + +struct hif_device_mbox_info { + u32 MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in + and ARRAY of 32-bit words */ + + /* the following describe extended mailbox properties */ + struct hif_mbox_properties MboxProp[4]; + /* if the HIF supports the GMbox extended address region it can report it + * here, some interfaces cannot support the GMBOX address range and not set this */ + u32 GMboxAddress; + u32 GMboxSize; + u32 Flags; /* flags to describe mbox behavior or usage */ + MBOX_BUF_IF_TYPE MboxBusIFType; /* mailbox bus interface type */ +}; + +typedef enum { + HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all + interrupts before returning */ + HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts + using ASYNC I/O (that is HIFAckInterrupt can be called at a + later time */ +} HIF_DEVICE_IRQ_PROCESSING_MODE; + +typedef enum { + HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */ + HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */ + HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures + to completely power-off the module and associated hardware (i.e. cut power supplies) + */ +} HIF_DEVICE_POWER_CHANGE_TYPE; + +struct hif_device_irq_yield_params { + int RecvPacketYieldCount; /* max number of packets to force DSR to return */ +}; + + +struct hif_scatter_item { + u8 *pBuffer; /* CPU accessible address of buffer */ + int Length; /* length of transfer to/from this buffer */ + void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */ +}; + +struct hif_scatter_req; +typedef void ( *HIF_SCATTER_COMP_CB)(struct hif_scatter_req *); + +typedef enum _HIF_SCATTER_METHOD { + HIF_SCATTER_NONE = 0, + HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */ + HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */ +} HIF_SCATTER_METHOD; + +struct hif_scatter_req { + struct dl_list ListLink; /* link management */ + u32 Address; /* address for the read/write operation */ + u32 Request; /* request flags */ + u32 TotalLength; /* total length of entire transfer */ + u32 CallerFlags; /* caller specific flags can be stored here */ + HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */ + int CompletionStatus; /* status of completion */ + void *Context; /* caller context for this request */ + int ValidScatterEntries; /* number of valid entries set by caller */ + HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */ + void *HIFPrivate[4]; /* HIF private area */ + u8 *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */ + struct hif_scatter_item ScatterList[1]; /* start of scatter list */ +}; + +typedef struct hif_scatter_req * ( *HIF_ALLOCATE_SCATTER_REQUEST)(struct hif_device *device); +typedef void ( *HIF_FREE_SCATTER_REQUEST)(struct hif_device *device, struct hif_scatter_req *request); +typedef int ( *HIF_READWRITE_SCATTER)(struct hif_device *device, struct hif_scatter_req *request); + +struct hif_device_scatter_support_info { + /* information returned from HIF layer */ + HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc; + HIF_FREE_SCATTER_REQUEST pFreeReqFunc; + HIF_READWRITE_SCATTER pReadWriteScatterFunc; + int MaxScatterEntries; + int MaxTransferSizePerScatterReq; +}; + +struct hif_device_os_device_info { + void *pOSDevice; +}; + +#define HIF_MAX_DEVICES 1 + +struct htc_callbacks { + void *context; /* context to pass to the dsrhandler + note : rwCompletionHandler is provided the context passed to HIFReadWrite */ + int (* rwCompletionHandler)(void *rwContext, int status); + int (* dsrHandler)(void *context); +}; + +typedef struct osdrv_callbacks { + void *context; /* context to pass for all callbacks except deviceRemovedHandler + the deviceRemovedHandler is only called if the device is claimed */ + int (* deviceInsertedHandler)(void *context, void *hif_handle); + int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle); + int (* deviceSuspendHandler)(void *context); + int (* deviceResumeHandler)(void *context); + int (* deviceWakeupHandler)(void *context); + int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config); +} OSDRV_CALLBACKS; + +#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host + needs to read the register table to figure out what */ +#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */ + +struct hif_pending_events_info { + u32 Events; + u32 LookAhead; + u32 AvailableRecvBytes; +#ifdef THREAD_X + u32 Polling; + u32 INT_CAUSE_REG; +#endif +}; + + /* function to get pending events , some HIF modules use special mechanisms + * to detect packet available and other interrupts */ +typedef int ( *HIF_PENDING_EVENTS_FUNC)(struct hif_device *device, + struct hif_pending_events_info *pEvents, + void *AsyncContext); + +#define HIF_MASK_RECV true +#define HIF_UNMASK_RECV false + /* function to mask recv events */ +typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(struct hif_device *device, + bool Mask, + void *AsyncContext); + + +/* + * This API is used to perform any global initialization of the HIF layer + * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer + * + */ +int HIFInit(OSDRV_CALLBACKS *callbacks); + +/* This API claims the HIF device and provides a context for handling removal. + * The device removal callback is only called when the OSDRV layer claims + * a device. The claimed context must be non-NULL */ +void HIFClaimDevice(struct hif_device *device, void *claimedContext); +/* release the claimed device */ +void HIFReleaseDevice(struct hif_device *device); + +/* This API allows the HTC layer to attach to the HIF device */ +int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks); +/* This API detaches the HTC layer from the HIF device */ +void HIFDetachHTC(struct hif_device *device); + +/* + * This API is used to provide the read/write interface over the specific bus + * interface. + * address - Starting address in the AR6000's address space. For mailbox + * writes, it refers to the start of the mbox boundary. It should + * be ensured that the last byte falls on the mailbox's EOM. For + * mailbox reads, it refers to the end of the mbox boundary. + * buffer - Pointer to the buffer containg the data to be transmitted or + * received. + * length - Amount of data to be transmitted or received. + * request - Characterizes the attributes of the command. + */ +int +HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context); + +/* + * This can be initiated from the unload driver context when the OSDRV layer has no more use for + * the device. + */ +void HIFShutDownDevice(struct hif_device *device); + +/* + * This should translate to an acknowledgment to the bus driver indicating that + * the previous interrupt request has been serviced and the all the relevant + * sources have been cleared. HTC is ready to process more interrupts. + * This should prevent the bus driver from raising an interrupt unless the + * previous one has been serviced and acknowledged using the previous API. + */ +void HIFAckInterrupt(struct hif_device *device); + +void HIFMaskInterrupt(struct hif_device *device); + +void HIFUnMaskInterrupt(struct hif_device *device); + +#ifdef THREAD_X +/* + * This set of functions are to be used by the bus driver to notify + * the HIF module about various events. + * These are not implemented if the bus driver provides an alternative + * way for this notification though callbacks for instance. + */ +int HIFInsertEventNotify(void); + +int HIFRemoveEventNotify(void); + +int HIFIRQEventNotify(void); + +int HIFRWCompleteEventNotify(void); +#endif + +int +HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u32 configLen); + +/* + * This API wait for the remaining MBOX messages to be drained + * This should be moved to HTC AR6K layer + */ +int hifWaitForPendingRecv(struct hif_device *device); + +#ifdef __cplusplus +} +#endif + +#endif /* _HIF_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/host_version.h b/trunk/drivers/staging/ath6kl/include/host_version.h new file mode 100644 index 000000000000..74f1982c681b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/host_version.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains version information for the sample host driver for the +// AR6000 chip +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_VERSION_H_ +#define _HOST_VERSION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * The version number is made up of major, minor, patch and build + * numbers. These are 16 bit numbers. The build and release script will + * set the build number using a Perforce counter. Here the build number is + * set to 9999 so that builds done without the build-release script are easily + * identifiable. + */ + +#define ATH_SW_VER_MAJOR __VER_MAJOR_ +#define ATH_SW_VER_MINOR __VER_MINOR_ +#define ATH_SW_VER_PATCH __VER_PATCH_ +#define ATH_SW_VER_BUILD __BUILD_NUMBER_ + +#ifdef __cplusplus +} +#endif + +#endif /* _HOST_VERSION_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/htc_api.h b/trunk/drivers/staging/ath6kl/include/htc_api.h new file mode 100644 index 000000000000..4fb767559f82 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/htc_api.h @@ -0,0 +1,575 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HTC_API_H_ +#define _HTC_API_H_ + +#include "htc_packet.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* TODO.. for BMI */ +#define ENDPOINT1 0 +// TODO -remove me, but we have to fix BMI first +#define HTC_MAILBOX_NUM_MAX 4 + +/* this is the amount of header room required by users of HTC */ +#define HTC_HEADER_LEN HTC_HDR_LENGTH + +typedef void *HTC_HANDLE; + +typedef u16 HTC_SERVICE_ID; + +struct htc_init_info { + void *pContext; /* context for target failure notification */ + void (*TargetFailure)(void *Instance, int Status); +}; + +/* per service connection send completion */ +typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,struct htc_packet *); +/* per service connection callback when a plurality of packets have been sent + * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of completed send packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,struct htc_packet_queue *); +/* per service connection pkt received */ +typedef void (*HTC_EP_RECV_PKT)(void *,struct htc_packet *); +/* per service connection callback when a plurality of packets are received + * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of recv packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_RECV_PKT_MULTIPLE)(void *,struct htc_packet_queue *); + +/* Optional per service connection receive buffer re-fill callback, + * On some OSes (like Linux) packets are allocated from a global pool and indicated up + * to the network stack. The driver never gets the packets back from the OS. For these OSes + * a refill callback can be used to allocate and re-queue buffers into HTC. + * + * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and + * the driver can re-queue these buffers into HTC. In this regard a refill callback is + * unnecessary */ +typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint); + +/* Optional per service connection receive buffer allocation callback. + * On some systems packet buffers are an extremely limited resource. Rather than + * queue largest-possible-sized buffers to HTC, some systems would rather + * allocate a specific size as the packet is received. The trade off is + * slightly more processing (callback invoked for each RX packet) + * for the benefit of committing fewer buffer resources into HTC. + * + * The callback is provided the length of the pending packet to fetch. This includes the + * HTC header length plus the length of payload. The callback can return a pointer to + * the allocated HTC packet for immediate use. + * + * Alternatively a variant of this handler can be used to allocate large receive packets as needed. + * For example an application can use the refill mechanism for normal packets and the recv-alloc mechanism to + * handle the case where a large packet buffer is required. This can significantly reduce the + * amount of "committed" memory used to receive packets. + * + * */ +typedef struct htc_packet *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length); + +typedef enum _HTC_SEND_FULL_ACTION { + HTC_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */ + HTC_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */ +} HTC_SEND_FULL_ACTION; + +/* Optional per service connection callback when a send queue is full. This can occur if the + * host continues queueing up TX packets faster than credits can arrive + * To prevent the host (on some Oses like Linux) from continuously queueing packets + * and consuming resources, this callback is provided so that that the host + * can disable TX in the subsystem (i.e. network stack). + * This callback is invoked for each packet that "overflows" the HTC queue. The callback can + * determine whether the new packet that overflowed the queue can be kept (HTC_SEND_FULL_KEEP) or + * dropped (HTC_SEND_FULL_DROP). If a packet is dropped, the EpTxComplete handler will be called + * and the packet's status field will be set to A_NO_RESOURCE. + * Other OSes require a "per-packet" indication for each completed TX packet, this + * closed loop mechanism will prevent the network stack from overunning the NIC + * The packet to keep or drop is passed for inspection to the registered handler the handler + * must ONLY inspect the packet, it may not free or reclaim the packet. */ +typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, struct htc_packet *pPacket); + +struct htc_ep_callbacks { + void *pContext; /* context for each callback */ + HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */ + HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */ + HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */ + HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */ + HTC_EP_RECV_ALLOC EpRecvAlloc; /* OPTIONAL recv allocation callback */ + HTC_EP_RECV_ALLOC EpRecvAllocThresh; /* OPTIONAL recv allocation callback based on a threshold */ + HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; /* OPTIONAL completion handler for multiple complete + indications (EpTxComplete must be NULL) */ + HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple + recv packet indications (EpRecv must be NULL) */ + int RecvAllocThreshold; /* if EpRecvAllocThresh is non-NULL, HTC will compare the + threshold value to the current recv packet length and invoke + the EpRecvAllocThresh callback to acquire a packet buffer */ + int RecvRefillWaterMark; /* if a EpRecvRefill handler is provided, this value + can be used to set a trigger refill callback + when the recv queue drops below this value + if set to 0, the refill is only called when packets + are empty */ +}; + +/* service connection information */ +struct htc_service_connect_req { + HTC_SERVICE_ID ServiceID; /* service ID to connect to */ + u16 ConnectionFlags; /* connection flags, see htc protocol definition */ + u8 *pMetaData; /* ptr to optional service-specific meta-data */ + u8 MetaDataLength; /* optional meta data length */ + struct htc_ep_callbacks EpCallbacks; /* endpoint callbacks */ + int MaxSendQueueDepth; /* maximum depth of any send queue */ + u32 LocalConnectionFlags; /* HTC flags for the host-side (local) connection */ + unsigned int MaxSendMsgSize; /* override max message size in send direction */ +}; + +#define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0) /* enable send bundle padding for this endpoint */ + +/* service connection response information */ +struct htc_service_connect_resp { + u8 *pMetaData; /* caller supplied buffer to optional meta-data */ + u8 BufferLength; /* length of caller supplied buffer */ + u8 ActualLength; /* actual length of meta data */ + HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */ + unsigned int MaxMsgLength; /* max length of all messages over this endpoint */ + u8 ConnectRespCode; /* connect response code from target */ +}; + +/* endpoint distribution structure */ +struct htc_endpoint_credit_dist { + struct htc_endpoint_credit_dist *pNext; + struct htc_endpoint_credit_dist *pPrev; + HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */ + HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */ + u32 DistFlags; /* distribution flags, distribution function can + set default activity using SET_EP_ACTIVE() macro */ + int TxCreditsNorm; /* credits for normal operation, anything above this + indicates the endpoint is over-subscribed, this field + is only relevant to the credit distribution function */ + int TxCreditsMin; /* floor for credit distribution, this field is + only relevant to the credit distribution function */ + int TxCreditsAssigned; /* number of credits assigned to this EP, this field + is only relevant to the credit dist function */ + int TxCredits; /* current credits available, this field is used by + HTC to determine whether a message can be sent or + must be queued */ + int TxCreditsToDist; /* pending credits to distribute on this endpoint, this + is set by HTC when credit reports arrive. + The credit distribution functions sets this to zero + when it distributes the credits */ + int TxCreditsSeek; /* this is the number of credits that the current pending TX + packet needs to transmit. This is set by HTC when + and endpoint needs credits in order to transmit */ + int TxCreditSize; /* size in bytes of each credit (set by HTC) */ + int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */ + void *pHTCReserved; /* reserved for HTC use */ + int TxQueueDepth; /* current depth of TX queue , i.e. messages waiting for credits + This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE + or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint + that has non-zero credits to recover + */ +}; + +#define HTC_EP_ACTIVE ((u32) (1u << 31)) + +/* macro to check if an endpoint has gone active, useful for credit + * distributions */ +#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE) +#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE + + /* credit distibution code that is passed into the distrbution function, + * there are mandatory and optional codes that must be handled */ +typedef enum _HTC_CREDIT_DIST_REASON { + HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed + send operations (MANDATORY) resulting in credit reports */ + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occurred (OPTIONAL) */ + HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */ + HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by + the distribution function */ +} HTC_CREDIT_DIST_REASON; + +typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context, + struct htc_endpoint_credit_dist *pEPList, + HTC_CREDIT_DIST_REASON Reason); + +typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits); + + /* endpoint statistics action */ +typedef enum _HTC_ENDPOINT_STAT_ACTION { + HTC_EP_STAT_SAMPLE = 0, /* only read statistics */ + HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */ + HTC_EP_STAT_CLEAR /* clear only */ +} HTC_ENDPOINT_STAT_ACTION; + + /* endpoint statistics */ +struct htc_endpoint_stats { + u32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on + this endpoint */ + u32 TxIssued; /* running count of total TX packets issued */ + u32 TxPacketsBundled; /* running count of TX packets that were issued in bundles */ + u32 TxBundles; /* running count of TX bundles that were issued */ + u32 TxDropped; /* tx packets that were dropped */ + u32 TxCreditRpts; /* running count of total credit reports received for this endpoint */ + u32 TxCreditRptsFromRx; /* credit reports received from this endpoint's RX packets */ + u32 TxCreditRptsFromOther; /* credit reports received from RX packets of other endpoints */ + u32 TxCreditRptsFromEp0; /* credit reports received from endpoint 0 RX packets */ + u32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */ + u32 TxCreditsFromOther; /* count of credits received via another endpoint */ + u32 TxCreditsFromEp0; /* count of credits received via another endpoint */ + u32 TxCreditsConsummed; /* count of consummed credits */ + u32 TxCreditsReturned; /* count of credits returned */ + u32 RxReceived; /* count of RX packets received */ + u32 RxLookAheads; /* count of lookahead records + found in messages received on this endpoint */ + u32 RxPacketsBundled; /* count of recv packets received in a bundle */ + u32 RxBundleLookAheads; /* count of number of bundled lookaheads */ + u32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */ + u32 RxAllocThreshHit; /* count of the number of times the recv allocation threshold was hit */ + u32 RxAllocThreshBytes; /* total number of bytes */ +}; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Create an instance of HTC over the underlying HIF device + @function name: HTCCreate + @input: HifDevice - hif device handle, + pInfo - initialization information + @output: + @return: HTC_HANDLE on success, NULL on failure + @notes: + @example: + @see also: HTCDestroy ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HTC_HANDLE HTCCreate(void *HifDevice, struct htc_init_info *pInfo); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the underlying HIF device handle + @function name: HTCGetHifDevice + @input: HTCHandle - handle passed into the AddInstance callback + @output: + @return: opaque HIF device handle usable in HIF API calls. + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set credit distribution parameters + @function name: HTCSetCreditDistribution + @input: HTCHandle - HTC handle + pCreditDistCont - caller supplied context to pass into distribution functions + CreditDistFunc - Distribution function callback + CreditDistInit - Credit Distribution initialization callback + ServicePriorityOrder - Array containing list of service IDs, lowest index is highest + priority + ListLength - number of elements in ServicePriorityOrder + @output: + @return: + @notes: The user can set a custom credit distribution function to handle special requirements + for each endpoint. A default credit distribution routine can be used by setting + CreditInitFunc to NULL. The default credit distribution is only provided for simple + "fair" credit distribution without regard to any prioritization. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Wait for the target to indicate the HTC layer is ready + @function name: HTCWaitTarget + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API blocks until the target responds with an HTC ready message. + The caller should not connect services until the target has indicated it is + ready. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCWaitTarget(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start target service communications + @function name: HTCStart + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API indicates to the target that the service connection phase is complete + and the target can freely start all connected services. This API should only be + called AFTER all service connections have been made. TCStart will issue a + SETUP_COMPLETE message to the target to indicate that all service connections + have been made and the target can start communicating over the endpoints. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCStart(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packet to HTC + @function name: HTCAddReceivePkt + @input: HTCHandle - HTC handle + pPacket - HTC receive packet to add + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Connect to an HTC service + @function name: HTCConnectService + @input: HTCHandle - HTC handle + pReq - connection details + @output: pResp - connection response + @return: + @notes: Service connections must be performed before HTCStart. User provides callback handlers + for various endpoint events. + @example: + @see also: HTCStart ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCConnectService(HTC_HANDLE HTCHandle, + struct htc_service_connect_req *pReq, + struct htc_service_connect_resp *pResp); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet + @function name: HTCSendPkt + @input: HTCHandle - HTC handle + pPacket - packet to send + @output: + @return: 0 + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro. + This interface is fully asynchronous. On error, HTC SendPkt will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HTC service communications + @function name: HTCStop + @input: HTCHandle - HTC handle + @output: + @return: + @notes: HTC communications is halted. All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCStop(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Destroy HTC service + @function name: HTCDestroy + @input: HTCHandle + @output: + @return: + @notes: This cleans up all resources allocated by HTCCreate(). + @example: + @see also: HTCCreate ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDestroy(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Flush pending TX packets + @function name: HTCFlushEndpoint + @input: HTCHandle - HTC handle + Endpoint - Endpoint to flush + Tag - flush tag + @output: + @return: + @notes: The Tag parameter is used to selectively flush packets with matching tags. + The value of 0 forces all packets to be flush regardless of tag. + @example: + @see also: HTCSendPkt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Dump credit distribution state + @function name: HTCDumpCreditStates + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This dumps all credit distribution information to the debugger + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDumpCreditStates(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Indicate a traffic activity change on an endpoint + @function name: HTCIndicateActivityChange + @input: HTCHandle - HTC handle + Endpoint - endpoint in which activity has changed + Active - true if active, false if it has become inactive + @output: + @return: + @notes: This triggers the registered credit distribution function to + re-adjust credits for active/inactive endpoints. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + bool Active); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get endpoint statistics + @function name: HTCGetEndpointStatistics + @input: HTCHandle - HTC handle + Endpoint - Endpoint identifier + Action - action to take with statistics + @output: + pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR) + + @return: true if statistics profiling is enabled, otherwise false. + + @notes: Statistics is a compile-time option and this function may return false + if HTC is not compiled with profiling. + + The caller can specify the statistic "action" to take when sampling + the statistics. This includes: + + HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values. + HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics + are cleared. + HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for + pStats + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + struct htc_endpoint_stats *pStats); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Unblock HTC message reception + @function name: HTCUnblockRecv + @input: HTCHandle - HTC handle + @output: + @return: + @notes: + HTC will block the receiver if the EpRecvAlloc callback fails to provide a packet. + The caller can use this API to indicate to HTC when resources (buffers) are available + such that the receiver can be unblocked and HTC may re-attempt fetching the pending message. + + This API is not required if the user uses the EpRecvRefill callback or uses the HTCAddReceivePacket() + API to recycle or provide receive packets to HTC. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCUnblockRecv(HTC_HANDLE HTCHandle); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: send a series of HTC packets + @function name: HTCSendPktsMultiple + @input: HTCHandle - HTC handle + pPktQueue - local queue holding packets to send + @output: + @return: 0 + @notes: Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro. + The queue must only contain packets directed at the same endpoint. + Caller supplies a pointer to an struct htc_packet_queue structure holding the TX packets in FIFO order. + This API will remove the packets from the pkt queue and place them into the HTC Tx Queue + and bundle messages where possible. + The caller may allocate the pkt queue on the stack to hold the packets. + This interface is fully asynchronous. On error, HTCSendPkts will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add multiple receive packets to HTC + @function name: HTCAddReceivePktMultiple + @input: HTCHandle - HTC handle + pPktQueue - HTC receive packet queue holding packets to add + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. The queue must only contain recv packets for the same endpoint. + Caller supplies a pointer to an struct htc_packet_queue structure holding the recv packet. + This API will remove the packets from the pkt queue and place them into internal + recv packet list. + The caller may allocate the pkt queue on the stack to hold the packets. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Check if an endpoint is marked active + @function name: HTCIsEndpointActive + @input: HTCHandle - HTC handle + Endpoint - endpoint to check for active state + @output: + @return: returns true if Endpoint is Active + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +bool HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the number of recv buffers currently queued into an HTC endpoint + @function name: HTCGetNumRecvBuffers + @input: HTCHandle - HTC handle + Endpoint - endpoint to check + @output: + @return: returns number of buffers in queue + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + +/* internally used functions for testing... */ +void HTCEnableRecv(HTC_HANDLE HTCHandle); +void HTCDisableRecv(HTC_HANDLE HTCHandle); +int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle, + u32 TimeoutInMs, + bool *pbIsRecvPending); + +#ifdef __cplusplus +} +#endif + +#endif /* _HTC_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/htc_packet.h b/trunk/drivers/staging/ath6kl/include/htc_packet.h new file mode 100644 index 000000000000..ba65c34ebc9c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/htc_packet.h @@ -0,0 +1,227 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef HTC_PACKET_H_ +#define HTC_PACKET_H_ + + +#include "dl_list.h" + +/* ------ Endpoint IDS ------ */ +typedef enum +{ + ENDPOINT_UNUSED = -1, + ENDPOINT_0 = 0, + ENDPOINT_1 = 1, + ENDPOINT_2 = 2, + ENDPOINT_3, + ENDPOINT_4, + ENDPOINT_5, + ENDPOINT_6, + ENDPOINT_7, + ENDPOINT_8, + ENDPOINT_MAX, +} HTC_ENDPOINT_ID; + +struct htc_packet; + +typedef void (* HTC_PACKET_COMPLETION)(void *,struct htc_packet *); + +typedef u16 HTC_TX_TAG; + +struct htc_tx_packet_info { + HTC_TX_TAG Tag; /* tag used to selective flush packets */ + int CreditsUsed; /* number of credits used for this TX packet (HTC internal) */ + u8 SendFlags; /* send flags (HTC internal) */ + int SeqNo; /* internal seq no for debugging (HTC internal) */ +}; + +#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */ +#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */ +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */ + +struct htc_rx_packet_info { + u32 ExpectedHdr; /* HTC internal use */ + u32 HTCRxFlags; /* HTC internal use */ + u32 IndicationFlags; /* indication flags set on each RX packet indication */ +}; + +#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) /* more packets on this endpoint are being fetched */ + +/* wrapper around endpoint-specific packets */ +struct htc_packet { + struct dl_list ListLink; /* double link */ + void *pPktContext; /* caller's per packet specific context */ + + u8 *pBufferStart; /* the true buffer start , the caller can + store the real buffer start here. In + receive callbacks, the HTC layer sets pBuffer + to the start of the payload past the header. This + field allows the caller to reset pBuffer when it + recycles receive packets back to HTC */ + /* + * Pointer to the start of the buffer. In the transmit + * direction this points to the start of the payload. In the + * receive direction, however, the buffer when queued up + * points to the start of the HTC header but when returned + * to the caller points to the start of the payload + */ + u8 *pBuffer; /* payload start (RX/TX) */ + u32 BufferLength; /* length of buffer */ + u32 ActualLength; /* actual length of payload */ + HTC_ENDPOINT_ID Endpoint; /* endpoint that this packet was sent/recv'd from */ + int Status; /* completion status */ + union { + struct htc_tx_packet_info AsTx; /* Tx Packet specific info */ + struct htc_rx_packet_info AsRx; /* Rx Packet specific info */ + } PktInfo; + + /* the following fields are for internal HTC use */ + HTC_PACKET_COMPLETION Completion; /* completion */ + void *pContext; /* HTC private completion context */ +}; + + + +#define COMPLETE_HTC_PACKET(p,status) \ +{ \ + (p)->Status = (status); \ + (p)->Completion((p)->pContext,(p)); \ +} + +#define INIT_HTC_PACKET_INFO(p,b,len) \ +{ \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ +} + +/* macro to set an initial RX packet for refilling HTC */ +#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ + (p)->Endpoint = (ep); \ +} + +/* fast macro to recycle an RX packet that will be re-queued to HTC */ +#define HTC_PACKET_RESET_RX(p) \ + { (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; } + +/* macro to set packet parameters for TX */ +#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->ActualLength = (len); \ + (p)->Endpoint = (ep); \ + (p)->PktInfo.AsTx.Tag = (tag); \ +} + +/* HTC Packet Queueing Macros */ +struct htc_packet_queue { + struct dl_list QueueHead; + int Depth; +}; + +/* initialize queue */ +#define INIT_HTC_PACKET_QUEUE(pQ) \ +{ \ + DL_LIST_INIT(&(pQ)->QueueHead); \ + (pQ)->Depth = 0; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE(pQ,p) \ +{ DL_ListInsertTail(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \ +{ DL_ListInsertHead(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} +/* test if a queue is empty */ +#define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0) +/* get packet at head without removing it */ +static INLINE struct htc_packet *HTC_GET_PKT_AT_HEAD(struct htc_packet_queue *queue) { + if (queue->Depth == 0) { + return NULL; + } + return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),struct htc_packet,ListLink); +} +/* remove a packet from a queue, where-ever it is in the queue */ +#define HTC_PACKET_REMOVE(pQ,p) \ +{ \ + DL_ListRemove(&(p)->ListLink); \ + (pQ)->Depth--; \ +} + +/* dequeue an HTC packet from the head of the queue */ +static INLINE struct htc_packet *HTC_PACKET_DEQUEUE(struct htc_packet_queue *queue) { + struct dl_list *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink); + } + return NULL; +} + +/* dequeue an HTC packet from the tail of the queue */ +static INLINE struct htc_packet *HTC_PACKET_DEQUEUE_TAIL(struct htc_packet_queue *queue) { + struct dl_list *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink); + } + return NULL; +} + +#define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth + + +#define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint +#define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag + + /* transfer the packets from one queue to the tail of another queue */ +#define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest,pQSrc) \ +{ \ + DL_ListTransferItemsToTail(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \ + (pQDest)->Depth += (pQSrc)->Depth; \ + (pQSrc)->Depth = 0; \ +} + + /* fast version to init and add a single packet to a queue */ +#define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ,pP) \ +{ \ + DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead,&(pP)->ListLink) \ + (pQ)->Depth = 1; \ +} + +#define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \ + ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), struct htc_packet, ListLink) + +#define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END + +#endif /*HTC_PACKET_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/wlan_api.h b/trunk/drivers/staging/ath6kl/include/wlan_api.h new file mode 100644 index 000000000000..9eea5875dd38 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/wlan_api.h @@ -0,0 +1,128 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the API for the host wlan module +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_WLAN_API_H_ +#define _HOST_WLAN_API_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct ieee80211_node_table; +struct ieee80211_frame; + +struct ieee80211_common_ie { + u16 ie_chan; + u8 *ie_tstamp; + u8 *ie_ssid; + u8 *ie_rates; + u8 *ie_xrates; + u8 *ie_country; + u8 *ie_wpa; + u8 *ie_rsn; + u8 *ie_wmm; + u8 *ie_ath; + u16 ie_capInfo; + u16 ie_beaconInt; + u8 *ie_tim; + u8 *ie_chswitch; + u8 ie_erp; + u8 *ie_wsc; + u8 *ie_htcap; + u8 *ie_htop; +#ifdef WAPI_ENABLE + u8 *ie_wapi; +#endif +}; + +typedef struct bss { + u8 ni_macaddr[6]; + u8 ni_snr; + s16 ni_rssi; + struct bss *ni_list_next; + struct bss *ni_list_prev; + struct bss *ni_hash_next; + struct bss *ni_hash_prev; + struct ieee80211_common_ie ni_cie; + u8 *ni_buf; + u16 ni_framelen; + struct ieee80211_node_table *ni_table; + u32 ni_refcnt; + int ni_scangen; + + u32 ni_tstamp; + u32 ni_actcnt; +#ifdef OS_ROAM_MANAGEMENT + u32 ni_si_gen; +#endif +} bss_t; + +typedef void wlan_node_iter_func(void *arg, bss_t *); + +bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size); +void wlan_node_free(bss_t *ni); +void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, + const u8 *macaddr); +bss_t *wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr); +void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni); +void wlan_free_allnodes(struct ieee80211_node_table *nt); +void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, + void *arg); + +void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt); +void wlan_node_table_reset(struct ieee80211_node_table *nt); +void wlan_node_table_cleanup(struct ieee80211_node_table *nt); + +int wlan_parse_beacon(u8 *buf, int framelen, + struct ieee80211_common_ie *cie); + +u16 wlan_ieee2freq(int chan); +u32 wlan_freq2ieee(u16 freq); + +void wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge); + +void +wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt); + +bss_t * +wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID); + +void +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni); + +bss_t *wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid); + +bss_t * +wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp); + +#ifdef __cplusplus +} +#endif + +#endif /* _HOST_WLAN_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/wmi_api.h b/trunk/drivers/staging/ath6kl/include/wmi_api.h new file mode 100644 index 000000000000..c8583e0c4a96 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/wmi_api.h @@ -0,0 +1,441 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions for the Wireless Module Interface (WMI). +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _WMI_API_H_ +#define _WMI_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + /* WMI converts a dix frame with an ethernet payload (up to 1500 bytes) + * to an 802.3 frame (adds SNAP header) and adds on a WMI data header */ +#define WMI_MAX_TX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + + /* A normal WMI data frame */ +#define WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + + /* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */ +#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH (3840 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + +/* + * IP QoS Field definitions according to 802.1p + */ +#define BEST_EFFORT_PRI 0 +#define BACKGROUND_PRI 1 +#define EXCELLENT_EFFORT_PRI 3 +#define CONTROLLED_LOAD_PRI 4 +#define VIDEO_PRI 5 +#define VOICE_PRI 6 +#define NETWORK_CONTROL_PRI 7 +#define MAX_NUM_PRI 8 + +#define UNDEFINED_PRI (0xff) + +#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */ + +#define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +typedef enum { + ATHEROS_COMPLIANCE = 0x1, +}TSPEC_PARAM_COMPLIANCE; + +struct wmi_t; + +void *wmi_init(void *devt); + +void wmi_qos_state_init(struct wmi_t *wmip); +void wmi_shutdown(struct wmi_t *wmip); +HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip); +void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid); +u16 wmi_get_mapped_qos_queue(struct wmi_t *, u8 ); +int wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf); +int wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS); +int wmi_dot3_2_dix(void *osbuf); + +int wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf); +int wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode); + +int wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf); +int wmi_syncpoint(struct wmi_t *wmip); +int wmi_syncpoint_reset(struct wmi_t *wmip); +u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled); + +u8 wmi_determine_userPriority (u8 *pkt, u32 layer2Pri); + +int wmi_control_rx(struct wmi_t *wmip, void *osbuf); +void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg); +void wmi_free_allnodes(struct wmi_t *wmip); +bss_t *wmi_find_node(struct wmi_t *wmip, const u8 *macaddr); +void wmi_free_node(struct wmi_t *wmip, const u8 *macaddr); + + +typedef enum { + NO_SYNC_WMIFLAG = 0, + SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */ + SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */ + SYNC_BOTH_WMIFLAG, + END_WMIFLAG /* end marker */ +} WMI_SYNC_FLAG; + +int wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG flag); + +int wmi_connect_cmd(struct wmi_t *wmip, + NETWORK_TYPE netType, + DOT11_AUTH_MODE dot11AuthMode, + AUTH_MODE authMode, + CRYPTO_TYPE pairwiseCrypto, + u8 pairwiseCryptoLen, + CRYPTO_TYPE groupCrypto, + u8 groupCryptoLen, + int ssidLength, + u8 *ssid, + u8 *bssid, + u16 channel, + u32 ctrl_flags); + +int wmi_reconnect_cmd(struct wmi_t *wmip, + u8 *bssid, + u16 channel); +int wmi_disconnect_cmd(struct wmi_t *wmip); +int wmi_getrev_cmd(struct wmi_t *wmip); +int wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, + u32 forceFgScan, u32 isLegacy, + u32 homeDwellTime, u32 forceScanInterval, + s8 numChan, u16 *channelList); +int wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, + u16 maxact_chdw_msec, u16 pas_chdw_msec, + u8 shScanRatio, u8 scanCtrlFlags, + u32 max_dfsch_act_time, + u16 maxact_scan_per_ssid); +int wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask); +int wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag, + u8 ssidLength, u8 *ssid); +int wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons); +int wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmisstime, u16 bmissbeacons); +int wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType, + u8 ieLen, u8 *ieInfo); +int wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode); +int wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl, + u16 atim_windows, u16 timeout_value); +int wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time, + u32 ps_period, u8 sleep_period); +int wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod, + u16 psPollNum, u16 dtimPolicy, + u16 wakup_tx_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy); +int wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout); +int wmi_sync_cmd(struct wmi_t *wmip, u8 syncNumber); +int wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream); +int wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 streamID); +int wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask); +int wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate); +int wmi_get_bitrate_cmd(struct wmi_t *wmip); +s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx); +int wmi_get_regDomain_cmd(struct wmi_t *wmip); +int wmi_get_channelList_cmd(struct wmi_t *wmip); +int wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam, + WMI_PHY_MODE mode, s8 numChan, + u16 *channelList); + +int wmi_set_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +int wmi_set_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +int wmi_clr_rssi_snr(struct wmi_t *wmip); +int wmi_set_lq_threshold_params(struct wmi_t *wmip, + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd); +int wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold); +int wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy); + +int wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 bitmask); + +int wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, + u32 source); + +int wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask, + u16 tsr, bool rep, u16 size, + u32 valid); + +int wmi_get_stats_cmd(struct wmi_t *wmip); + +int wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, + CRYPTO_TYPE keyType, u8 keyUsage, + u8 keyLength,u8 *keyRSC, + u8 *keyMaterial, u8 key_op_ctrl, u8 *mac, + WMI_SYNC_FLAG sync_flag); +int wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk); +int wmi_delete_krk_cmd(struct wmi_t *wmip); +int wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex); +int wmi_set_akmp_params_cmd(struct wmi_t *wmip, + WMI_SET_AKMP_PARAMS_CMD *akmpParams); +int wmi_get_pmkid_list_cmd(struct wmi_t *wmip); +int wmi_set_pmkid_list_cmd(struct wmi_t *wmip, + WMI_SET_PMKID_LIST_CMD *pmkInfo); +int wmi_abort_scan_cmd(struct wmi_t *wmip); +int wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM); +int wmi_get_txPwr_cmd(struct wmi_t *wmip); +int wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid); +int wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex); +int wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en); +int wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId, + bool set); +int wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, + u8 eCWmin, u8 eCWmax, + u8 aifsn); +int wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType, + u8 trafficClass, u8 maxRetries, + u8 enableNotify); + +void wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid); + +int wmi_get_roam_tbl_cmd(struct wmi_t *wmip); +int wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType); +int wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, + u8 size); +int wmi_set_powersave_timers_cmd(struct wmi_t *wmip, + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, + u8 size); + +int wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode); +int wmi_opt_tx_frame_cmd(struct wmi_t *wmip, + u8 frmType, + u8 *dstMacAddr, + u8 *bssid, + u16 optIEDataLen, + u8 *optIEData); + +int wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl); +int wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize); +int wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSpLen); +u8 convert_userPriority_to_trafficClass(u8 userPriority); +u8 wmi_get_power_mode_cmd(struct wmi_t *wmip); +int wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance); + +#ifdef CONFIG_HOST_TCMD_SUPPORT +int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len); +#endif + +int wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status); +int wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd); + +int wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd); + +int wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd); + +int wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd); + +int wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd); + +int wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd); + + +int wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd); + +int wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd); + +int wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd); + +int wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd); + +int wmi_get_btcoex_stats_cmd(struct wmi_t * wmip); + +int wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold); + +/* + * This function is used to configure the fix rates mask to the target. + */ +int wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask); +int wmi_get_ratemask_cmd(struct wmi_t *wmip); + +int wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode); + +int wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode); + +int wmi_set_qos_supp_cmd(struct wmi_t *wmip,u8 status); +int wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status); +int wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable); +int wmi_set_country(struct wmi_t *wmip, u8 *countryCode); + +int wmi_get_keepalive_configured(struct wmi_t *wmip); +u8 wmi_get_keepalive_cmd(struct wmi_t *wmip); +int wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval); + +int wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, + u8 ieLen,u8 *ieInfo); + +int wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen); + +s32 wmi_get_rate(s8 rateindex); + +int wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd); + +/*Wake on Wireless WMI commands*/ +int wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd); +int wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd); +int wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd); +int wmi_add_wow_pattern_cmd(struct wmi_t *wmip, + WMI_ADD_WOW_PATTERN_CMD *cmd, u8 *pattern, u8 *mask, u8 pattern_size); +int wmi_del_wow_pattern_cmd(struct wmi_t *wmip, + WMI_DEL_WOW_PATTERN_CMD *cmd); +int wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status); + +int +wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer); + +int +wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4); + +int +wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4); + +int +wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable); + +bss_t * +wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID); + + +void +wmi_node_return (struct wmi_t *wmip, bss_t *bss); + +void +wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge); + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +int wmi_prof_cfg_cmd(struct wmi_t *wmip, u32 period, u32 nbins); +int wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr); +int wmi_prof_start_cmd(struct wmi_t *wmip); +int wmi_prof_stop_cmd(struct wmi_t *wmip); +int wmi_prof_count_get_cmd(struct wmi_t *wmip); +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ +#ifdef OS_ROAM_MANAGEMENT +void wmi_scan_indication (struct wmi_t *wmip); +#endif + +int +wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd); + +bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id); +int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss); + + +/* + * AP mode + */ +int +wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p); + +int +wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid); + +int +wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta); + +int +wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy); + +int +wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a); + +u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl); + +int +wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason); + +int +wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag); + +int +wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period); + +int +wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell); + +int +wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim); + +int +wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset); + +int +wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd); + +int +wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width); + +int +wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz); + +int +wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray); + +int +wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid); + +int +wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink); + +int +wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask); + +int +wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, bool rxDot11Hdr, bool defragOnHost); + +int +wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode); + +int +wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence); + +int +wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk); + +int +wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd); + +u16 wmi_ieee2freq (int chan); + +u32 wmi_freq2ieee (u16 freq); + +bss_t * +wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, + u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp); + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c new file mode 100644 index 000000000000..e0ea2183019d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c @@ -0,0 +1,565 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR3K configuration implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "common_drv.h" +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include "export_hci_transport.h" +#else +#include "hci_transport_api.h" +#endif +#include "ar3kconfig.h" +#include "tlpm.h" + +#define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5 +#define HCI_EVENT_RESP_TIMEOUTMS 3000 +#define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0 +#define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1 +#define HCI_EVENT_OPCODE_BYTE_LOW 3 +#define HCI_EVENT_OPCODE_BYTE_HI 4 +#define HCI_CMD_COMPLETE_EVENT_CODE 0xE +#define HCI_MAX_EVT_RECV_LENGTH 257 +#define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5 + +int AthPSInitialize(struct ar3k_config_info *hdev); + +static int SendHCICommand(struct ar3k_config_info *pConfig, + u8 *pBuffer, + int Length) +{ + struct htc_packet *pPacket = NULL; + int status = 0; + + do { + + pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pPacket,sizeof(struct htc_packet)); + SET_HTC_PACKET_INFO_TX(pPacket, + NULL, + pBuffer, + Length, + HCI_COMMAND_TYPE, + AR6K_CONTROL_PKT_TAG); + + /* issue synchronously */ + status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true); + + } while (false); + + if (pPacket != NULL) { + kfree(pPacket); + } + + return status; +} + +static int RecvHCIEvent(struct ar3k_config_info *pConfig, + u8 *pBuffer, + int *pLength) +{ + int status = 0; + struct htc_packet *pRecvPacket = NULL; + + do { + + pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); + if (NULL == pRecvPacket) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); + break; + } + + A_MEMZERO(pRecvPacket,sizeof(struct htc_packet)); + + SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE); + + status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev, + pRecvPacket, + HCI_EVENT_RESP_TIMEOUTMS); + if (status) { + break; + } + + *pLength = pRecvPacket->ActualLength; + + } while (false); + + if (pRecvPacket != NULL) { + kfree(pRecvPacket); + } + + return status; +} + +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree) +{ + int status = 0; + u8 *pBuffer = NULL; + u8 *pTemp; + int length; + bool commandComplete = false; + u8 opCodeBytes[2]; + + do { + + length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength); + length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom; + length += pConfig->pHCIProps->IOBlockPad; + + pBuffer = (u8 *)A_MALLOC(length); + if (NULL == pBuffer) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n")); + status = A_NO_MEMORY; + break; + } + + /* get the opcodes to check the command complete event */ + opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET]; + opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET]; + + /* copy HCI command */ + memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength); + /* send command */ + status = SendHCICommand(pConfig, + pBuffer + pConfig->pHCIProps->HeadRoom, + CmdLength); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status)); + AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); + break; + } + + /* reuse buffer to capture command complete event */ + A_MEMZERO(pBuffer,length); + status = RecvHCIEvent(pConfig,pBuffer,&length); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n")); + AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); + break; + } + + pTemp = pBuffer + pConfig->pHCIProps->HeadRoom; + if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) { + if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) && + (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) { + commandComplete = true; + } + } + + if (!commandComplete) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0])); + AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event"); + status = A_ECOMM; + break; + } + + if (ppEventBuffer != NULL) { + /* caller wants to look at the event */ + *ppEventBuffer = pTemp; + if (ppBufferToFree == NULL) { + status = A_EINVAL; + break; + } + /* caller must free the buffer */ + *ppBufferToFree = pBuffer; + pBuffer = NULL; + } + + } while (false); + + if (pBuffer != NULL) { + kfree(pBuffer); + } + + return status; +} + +static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig) +{ + int status = 0; + u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0}; + u16 baudVal; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + do { + + if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) { + baudVal = (u16)(pConfig->AR3KBaudRate / 100); + hciBaudChangeCommand[3] = (u8)baudVal; + hciBaudChangeCommand[4] = (u8)(baudVal >> 8); + + status = SendHCICommandWaitCommandComplete(pConfig, + hciBaudChangeCommand, + sizeof(hciBaudChangeCommand), + &pEvent, + &pBufferToFree); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n")); + break; + } + + if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: Baud change command event status failed: %d \n", + pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET])); + status = A_ECOMM; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate)); + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) { + /* some versions of AR3K do not switch baud immediately, up to 300MS */ + A_MDELAY(325); + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) { + /* Tell target to change UART baud rate for AR6K */ + status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: failed to set scale and step values: %d \n", status)); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate)); + } + + } while (false); + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KExitMinBoot(struct ar3k_config_info *pConfig) +{ + int status; + char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + status = SendHCICommandWaitCommandComplete(pConfig, + exitMinBootCmd, + sizeof(exitMinBootCmd), + &pEvent, + &pBufferToFree); + + if (!status) { + if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: MinBoot exit command event status failed: %d \n", + pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET])); + status = A_ECOMM; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("AR3K Config: MinBoot Exit Command Complete (Success) \n")); + A_MDELAY(1); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n")); + } + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig) +{ + int status = 0; + u8 hciResetCommand[] = {0x03,0x0c,0x0}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + status = SendHCICommandWaitCommandComplete( pConfig, + hciResetCommand, + sizeof(hciResetCommand), + &pEvent, + &pBufferToFree ); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n")); + } + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KEnableTLPM(struct ar3k_config_info *pConfig) +{ + int status; + /* AR3K vendor specific command for Host Wakeup Config */ + char hostWakeupConfig[] = {0x31,0xFC,0x18, + 0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms + 0x00,0x00,0x00,0x00, + TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms + 0x00,0x00,0x00,0x00}; + /* AR3K vendor specific command for Target Wakeup Config */ + char targetWakeupConfig[] = {0x31,0xFC,0x18, + 0x04,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms + 0x00,0x00,0x00,0x00, + TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms + 0x00,0x00,0x00,0x00}; + /* AR3K vendor specific command for Host Wakeup Enable */ + char hostWakeupEnable[] = {0x31,0xFC,0x4, + 0x01,0x00,0x00,0x00}; + /* AR3K vendor specific command for Target Wakeup Enable */ + char targetWakeupEnable[] = {0x31,0xFC,0x4, + 0x06,0x00,0x00,0x00}; + /* AR3K vendor specific command for Sleep Enable */ + char sleepEnable[] = {0x4,0xFC,0x1, + 0x1}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + if (0 != pConfig->IdleTimeout) { + u8 idle_lsb = pConfig->IdleTimeout & 0xFF; + u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8; + hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb; + hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb; + } + + if (0 != pConfig->WakeupTimeout) { + hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF); + } + + status = SendHCICommandWaitCommandComplete(pConfig, + hostWakeupConfig, + sizeof(hostWakeupConfig), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + targetWakeupConfig, + sizeof(targetWakeupConfig), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + hostWakeupEnable, + sizeof(hostWakeupEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + targetWakeupEnable, + sizeof(targetWakeupEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + sleepEnable, + sizeof(sleepEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n")); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status)); + + return status; +} + +int AR3KConfigure(struct ar3k_config_info *pConfig) +{ + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n")); + + do { + + if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { + status = A_EINVAL; + break; + } + + /* disable asynchronous recv while we issue commands and receive events synchronously */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); + if (status) { + break; + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) { + status = AR3KExitMinBoot(pConfig); + if (status) { + break; + } + } + + + /* Load patching and PST file if available*/ + if (0 != AthPSInitialize(pConfig)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n")); + } + + /* Send HCI reset to make PS tags take effect*/ + AR3KConfigureSendHCIReset(pConfig); + + if (pConfig->Flags & + (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { + status = AR3KConfigureHCIBaud(pConfig); + if (status) { + break; + } + } + + + + if (pConfig->PwrMgmtEnabled) { + /* the delay is required after the previous HCI reset before further + * HCI commands can be issued + */ + A_MDELAY(200); + AR3KEnableTLPM(pConfig); + } + + /* re-enable asynchronous recv */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); + if (status) { + break; + } + + + } while (false); + + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status)); + + return status; +} + +int AR3KConfigureExit(void *config) +{ + int status = 0; + struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n")); + + do { + + if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { + status = A_EINVAL; + break; + } + + /* disable asynchronous recv while we issue commands and receive events synchronously */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); + if (status) { + break; + } + + if (pConfig->Flags & + (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { + status = AR3KConfigureHCIBaud(pConfig); + if (status) { + break; + } + } + + /* re-enable asynchronous recv */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); + if (status) { + break; + } + + + } while (false); + + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status)); + + return status; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c new file mode 100644 index 000000000000..282ceac597b8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file implements the Atheros PS and patch downloaded for HCI UART Transport driver. + * This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO + * defined. + * + * + * ar3kcpsconfig.c + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + + +#include "ar3kpsconfig.h" +#ifndef HCI_TRANSPORT_SDIO +#include "hci_ath.h" +#include "hci_uart.h" +#endif /* #ifndef HCI_TRANSPORT_SDIO */ + +#define MAX_FW_PATH_LEN 50 +#define MAX_BDADDR_FORMAT_LENGTH 30 + +/* + * Structure used to send HCI packet, hci packet length and device info + * together as parameter to PSThread. + */ +typedef struct { + + struct ps_cmd_packet *HciCmdList; + u32 num_packets; + struct ar3k_config_info *dev; +}HciCommandListParam; + +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree); + +u32 Rom_Version; +u32 Build_Version; +extern bool BDADDR; + +int getDeviceType(struct ar3k_config_info *pConfig, u32 *code); +int ReadVersionInfo(struct ar3k_config_info *pConfig); +#ifndef HCI_TRANSPORT_SDIO + +DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent); +DECLARE_WAIT_QUEUE_HEAD(HciEvent); +u8 *HciEventpacket; +rwlock_t syncLock; +wait_queue_t Eventwait; + +int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len); +extern char *bdaddr; +#endif /* HCI_TRANSPORT_SDIO */ + +int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type); + +int PSSendOps(void *arg); + +#ifdef BT_PS_DEBUG +void Hci_log(u8 * log_string,u8 *data,u32 len) +{ + int i; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string)); + for (i = 0; i < len; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("0x%02x ", data[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n")); +} +#else +#define Hci_log(string,data,len) +#endif /* BT_PS_DEBUG */ + + + + +int AthPSInitialize(struct ar3k_config_info *hdev) +{ + int status = 0; + if(hdev == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n")); + return A_ERROR; + } + +#ifndef HCI_TRANSPORT_SDIO + DECLARE_WAITQUEUE(wait, current); +#endif /* HCI_TRANSPORT_SDIO */ + + +#ifdef HCI_TRANSPORT_SDIO + status = PSSendOps((void*)hdev); +#else + if(InitPSState(hdev) == -1) { + return A_ERROR; + } + allow_signal(SIGKILL); + add_wait_queue(&PsCompleteEvent,&wait); + set_current_state(TASK_INTERRUPTIBLE); + if(!kernel_thread(PSSendOps,(void*)hdev,CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Kthread Failed\n")); + remove_wait_queue(&PsCompleteEvent,&wait); + return A_ERROR; + } + wait_event_interruptible(PsCompleteEvent,(PSTagMode == false)); + set_current_state(TASK_RUNNING); + remove_wait_queue(&PsCompleteEvent,&wait); + +#endif /* HCI_TRANSPORT_SDIO */ + + + return status; + +} + +int PSSendOps(void *arg) +{ + int i; + int status = 0; + struct ps_cmd_packet *HciCmdList; /* List storing the commands */ + const struct firmware* firmware; + u32 numCmds; + u8 *event; + u8 *bufferToFree; + struct hci_dev *device; + u8 *buffer; + u32 len; + u32 DevType; + u8 *PsFileName; + u8 *patchFileName; + u8 *path = NULL; + u8 *config_path = NULL; + u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH]; + struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg; + struct device *firmwareDev = NULL; + status = 0; + HciCmdList = NULL; +#ifdef HCI_TRANSPORT_SDIO + device = hdev->pBtStackHCIDev; + firmwareDev = device->parent; +#else + device = hdev; + firmwareDev = &device->dev; + AthEnableSyncCommandOp(true); +#endif /* HCI_TRANSPORT_SDIO */ + /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different. + */ + + path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN); + if(path == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN)); + goto complete; + } + config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN); + if(config_path == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN)); + goto complete; + } + + if(A_ERROR == getDeviceType(hdev,&DevType)) { + status = 1; + goto complete; + } + if(A_ERROR == ReadVersionInfo(hdev)) { + status = 1; + goto complete; + } + + patchFileName = PATCH_FILE; + snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version); + if(DevType){ + if(DevType == 0xdeadc0de){ + PsFileName = PS_ASIC_FILE; + } else{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version)); + if((Rom_Version == 0x99999999) && (Build_Version == 1)){ + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n")); + patchFileName = NULL; + } + PsFileName = PS_FPGA_FILE; + } + } + else{ + PsFileName = PS_ASIC_FILE; + } + + snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path)); + /* Read the PS file to a dynamically allocated buffer */ + if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + buffer = (u8 *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + A_RELEASE_FIRMWARE(firmware); + /* Parse the PS buffer to a global variable */ + status = AthDoParsePS(buffer,len); + kfree(buffer); + } else { + A_RELEASE_FIRMWARE(firmware); + } + + + /* Read the patch file to a dynamically allocated buffer */ + if(patchFileName != NULL) + snprintf(config_path, + MAX_FW_PATH_LEN, "%s%s",path,patchFileName); + else { + status = 0; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); + if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + /* + * It is not necessary that Patch file be available, continue with PS Operations if. + * failed. + */ + status = 0; + + } else { + if(NULL == firmware || firmware->size == 0) { + status = 0; + } else { + buffer = (u8 *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + A_RELEASE_FIRMWARE(firmware); + /* parse and store the Patch file contents to a global variables */ + status = AthDoParsePatch(buffer,len); + kfree(buffer); + } else { + A_RELEASE_FIRMWARE(firmware); + } + } + } + + /* Create an HCI command list from the parsed PS and patch information */ + AthCreateCommandList(&HciCmdList,&numCmds); + + /* Form the parameter for PSSendOps() API */ + + + /* + * First Send the CRC packet, + * We have to continue with the PS operations only if the CRC packet has been replied with + * a Command complete event with status Error. + */ + + if(SendHCICommandWaitCommandComplete + (hdev, + HciCmdList[0].Hcipacket, + HciCmdList[0].packetLen, + &event, + &bufferToFree) == 0) { + if(ReadPSEvent(event) == 0) { /* Exit if the status is success */ + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + +#ifndef HCI_TRANSPORT_SDIO + if(bdaddr && bdaddr[0] !='\0') { + write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); + } +#endif + status = 1; + goto complete; + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + } else { + status = 0; + goto complete; + } + + for(i = 1; i bdaddr[0] !=0x00 || + hdev->bdaddr[1] !=0x00 || + hdev->bdaddr[2] !=0x00 || + hdev->bdaddr[3] !=0x00 || + hdev->bdaddr[4] !=0x00 || + hdev->bdaddr[5] !=0x00) + write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX); + +#ifndef HCI_TRANSPORT_SDIO + + if(bdaddr && bdaddr[0] != '\0') { + write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); + } else +#endif /* HCI_TRANSPORT_SDIO */ + /* Write BDADDR Read from OTP here */ + + + +#endif + + { + /* Read Contents of BDADDR file if user has not provided any option */ + snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); + if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1); + memcpy(config_bdaddr, firmware->data, len); + config_bdaddr[len] = '\0'; + write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); + A_RELEASE_FIRMWARE(firmware); + } +complete: +#ifndef HCI_TRANSPORT_SDIO + AthEnableSyncCommandOp(false); + PSTagMode = false; + wake_up_interruptible(&PsCompleteEvent); +#endif /* HCI_TRANSPORT_SDIO */ + if(NULL != HciCmdList) { + AthFreeCommandList(&HciCmdList,numCmds); + } + if(path) { + kfree(path); + } + if(config_path) { + kfree(config_path); + } + return status; +} +#ifndef HCI_TRANSPORT_SDIO +/* + * This API is used to send the HCI command to controller and return + * with a HCI Command Complete event. + * For HCI SDIO transport, this will be internally defined. + */ +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree) +{ + if(CmdLength == 0) { + return A_ERROR; + } + Hci_log("COM Write -->",pHCICommand,CmdLength); + PSAcked = false; + if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) { + /* If the controller is not available, return Error */ + return A_ERROR; + } + //add_timer(&psCmdTimer); + wait_event_interruptible(HciEvent,(PSAcked == true)); + if(NULL != HciEventpacket) { + *ppEventBuffer = HciEventpacket; + *ppBufferToFree = HciEventpacket; + } else { + /* Did not get an event from controller. return error */ + *ppBufferToFree = NULL; + return A_ERROR; + } + + return 0; +} +#endif /* HCI_TRANSPORT_SDIO */ + +int ReadPSEvent(u8* Data){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3])); + + if(Data[4] == 0xFC && Data[5] == 0x00) + { + switch(Data[3]){ + case 0x0B: + return 0; + break; + case 0x0C: + /* Change Baudrate */ + return 0; + break; + case 0x04: + return 0; + break; + case 0x1E: + Rom_Version = Data[9]; + Rom_Version = ((Rom_Version << 8) |Data[8]); + Rom_Version = ((Rom_Version << 8) |Data[7]); + Rom_Version = ((Rom_Version << 8) |Data[6]); + + Build_Version = Data[13]; + Build_Version = ((Build_Version << 8) |Data[12]); + Build_Version = ((Build_Version << 8) |Data[11]); + Build_Version = ((Build_Version << 8) |Data[10]); + return 0; + break; + + + } + } + + return A_ERROR; +} +int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr) +{ + unsigned char bdbyte[3]; + unsigned char *str_byte = str_bdaddr; + int i,j; + unsigned char colon_present = 0; + + if(NULL != strstr(str_bdaddr,":")) { + colon_present = 1; + } + + + bdbyte[2] = '\0'; + + for( i = 0,j = 5; i < 6; i++, j--) { + bdbyte[0] = str_byte[0]; + bdbyte[1] = str_byte[1]; + bdaddr[j] = A_STRTOL(bdbyte,NULL,16); + if(colon_present == 1) { + str_byte+=3; + } else { + str_byte+=2; + } + } + return 0; +} + +int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type) +{ + u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + u8 *event; + u8 *bufferToFree = NULL; + int result = A_ERROR; + int inc,outc; + + if (type == BDADDR_TYPE_STRING) + str2ba(bdaddr,&bdaddr_cmd[7]); + else { + /* Bdaddr has to be sent as LAP first */ + for(inc = 5 ,outc = 7; inc >=0; inc--, outc++) + bdaddr_cmd[outc] = bdaddr[inc]; + } + + if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, + sizeof(bdaddr_cmd), + &event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + if(event[3] == 0x0B){ + result = 0; + } + } + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; + +} +int ReadVersionInfo(struct ar3k_config_info *pConfig) +{ + u8 hciCommand[] = {0x1E,0xfc,0x00}; + u8 *event; + u8 *bufferToFree = NULL; + int result = A_ERROR; + if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + result = ReadPSEvent(event); + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; +} +int getDeviceType(struct ar3k_config_info *pConfig, u32 *code) +{ + u8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04}; + u8 *event; + u8 *bufferToFree = NULL; + u32 reg; + int result = A_ERROR; + *code = 0; + hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF); + hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF); + hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF); + hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF); + if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + switch(event[3]){ + case 0x05: + reg = event[9]; + reg = ((reg << 8) |event[8]); + reg = ((reg << 8) |event[7]); + reg = ((reg << 8) |event[6]); + *code = reg; + result = 0; + + break; + case 0x06: + //Sleep(500); + break; + } + } + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; +} + + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h new file mode 100644 index 000000000000..d44351307807 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file defines the symbols exported by Atheros PS and patch download module. + * define the constant HCI_TRANSPORT_SDIO if the module is being used for HCI SDIO transport. + * defined. + * + * + * ar3kcpsconfig.h + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + + +#ifndef __AR3KPSCONFIG_H +#define __AR3KPSCONFIG_H + +/* + * Define the flag HCI_TRANSPORT_SDIO and undefine HCI_TRANSPORT_UART if the transport being used is SDIO. + */ +#undef HCI_TRANSPORT_UART + +#include +#include +#include + + +#include +#include + + +#include +#include + +#include "ar3kpsparser.h" + +#define FPGA_REGISTER 0x4FFC +#define BDADDR_TYPE_STRING 0 +#define BDADDR_TYPE_HEX 1 +#define CONFIG_PATH "ar3k" + +#define PS_ASIC_FILE "PS_ASIC.pst" +#define PS_FPGA_FILE "PS_FPGA.pst" + +#define PATCH_FILE "RamPatch.txt" +#define BDADDR_FILE "ar3kbdaddr.pst" + +#define ROM_VER_AR3001_3_1_0 30000 +#define ROM_VER_AR3001_3_1_1 30101 + + +#ifndef HCI_TRANSPORT_SDIO +#define struct ar3k_config_info struct hci_dev +extern wait_queue_head_t HciEvent; +extern wait_queue_t Eventwait; +extern u8 *HciEventpacket; +#endif /* #ifndef HCI_TRANSPORT_SDIO */ + +int AthPSInitialize(struct ar3k_config_info *hdev); +int ReadPSEvent(u8* Data); +#endif /* __AR3KPSCONFIG_H */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c new file mode 100644 index 000000000000..c01c0cb0af4e --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file implements the Atheros PS and patch parser. + * It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands. + * + * + * + * ar3kpsparser.c + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + +#include "ar3kpsparser.h" + +#include +#include + +#define BD_ADDR_SIZE 6 +#define WRITE_PATCH 8 +#define ENABLE_PATCH 11 +#define PS_RESET 2 +#define PS_WRITE 1 +#define PS_VERIFY_CRC 9 +#define CHANGE_BDADDR 15 + +#define HCI_COMMAND_HEADER 7 + +#define HCI_EVENT_SIZE 7 + +#define WRITE_PATCH_COMMAND_STATUS_OFFSET 5 + +#define PS_RAM_SIZE 2048 + +#define RAM_PS_REGION (1<<0) +#define RAM_PATCH_REGION (1<<1) +#define RAMPS_MAX_PS_DATA_PER_TAG 20000 +#define MAX_RADIO_CFG_TABLE_SIZE 244 +#define RAMPS_MAX_PS_TAGS_PER_FILE 50 + +#define PS_MAX_LEN 500 +#define LINE_SIZE_MAX (PS_MAX_LEN *2) + +/* Constant values used by parser */ +#define BYTES_OF_PS_DATA_PER_LINE 16 +#define RAMPS_MAX_PS_DATA_PER_TAG 20000 + + +/* Number pf PS/Patch entries in an HCI packet */ +#define MAX_BYTE_LENGTH 244 + +#define SKIP_BLANKS(str) while (*str == ' ') str++ + +enum MinBootFileFormatE +{ + MB_FILEFORMAT_RADIOTBL, + MB_FILEFORMAT_PATCH, + MB_FILEFORMAT_COEXCONFIG +}; + +enum RamPsSection +{ + RAM_PS_SECTION, + RAM_PATCH_SECTION, + RAM_DYN_MEM_SECTION +}; + +enum eType { + eHex, + edecimal +}; + + +typedef struct tPsTagEntry +{ + u32 TagId; + u32 TagLen; + u8 *TagData; +} tPsTagEntry, *tpPsTagEntry; + +typedef struct tRamPatch +{ + u16 Len; + u8 *Data; +} tRamPatch, *ptRamPatch; + + + +struct st_ps_data_format { + enum eType eDataType; + bool bIsArray; +}; + +struct st_read_status { + unsigned uTagID; + unsigned uSection; + unsigned uLineCount; + unsigned uCharCount; + unsigned uByteCount; +}; + + +/* Stores the number of PS Tags */ +static u32 Tag_Count = 0; + +/* Stores the number of patch commands */ +static u32 Patch_Count = 0; +static u32 Total_tag_lenght = 0; +bool BDADDR = false; +u32 StartTagId; + +tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE]; +tRamPatch RamPatch[MAX_NUM_PATCH_ENTRY]; + + +int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat); +char AthReadChar(u8 *buffer, u32 len,u32 *pos); +char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos); +static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index); + +/* Function to reads the next character from the input buffer */ +char AthReadChar(u8 *buffer, u32 len,u32 *pos) +{ + char Ch; + if(buffer == NULL || *pos >=len ) + { + return '\0'; + } else { + Ch = buffer[*pos]; + (*pos)++; + return Ch; + } +} +/* PS parser helper function */ +unsigned int uGetInputDataFormat(char *pCharLine, struct st_ps_data_format *pstFormat) +{ + if(pCharLine[0] != '[') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + return 0; + } + switch(pCharLine[1]) { + case 'H': + case 'h': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A + return 1; + } + } + if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = false; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A + return 1; + } + } + else if(pCharLine[3] == ']') { //[H:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[H: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); + return 1; + } + break; + + case 'A': + case 'a': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H + return 1; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[A: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n")); + return 1; + } + break; + + case 'S': + case 's': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H + return 1; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[A: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n")); + return 1; + } + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n")); + return 1; + } +} + +unsigned int uReadDataInSection(char *pCharLine, struct st_ps_data_format stPS_DataFormat) +{ + char *pTokenPtr = pCharLine; + + if(pTokenPtr[0] == '[') { + while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') { + pTokenPtr++; + } + if(pTokenPtr[0] == '\0') { + return (0x0FFF); + } + pTokenPtr++; + + + } + if(stPS_DataFormat.eDataType == eHex) { + if(stPS_DataFormat.bIsArray == true) { + //Not implemented + return (0x0FFF); + } + else { + return (A_STRTOL(pTokenPtr, NULL, 16)); + } + } + else { + //Not implemented + return (0x0FFF); + } +} +int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat) +{ + char *Buffer; + char *pCharLine; + u8 TagCount; + u16 ByteCount; + u8 ParseSection=RAM_PS_SECTION; + u32 pos; + + + + int uReadCount; + struct st_ps_data_format stPS_DataFormat; + struct st_read_status stReadStatus = {0, 0, 0,0}; + pos = 0; + Buffer = NULL; + + if (srcbuffer == NULL || srclen == 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n")); + return A_ERROR; + } + TagCount = 0; + ByteCount = 0; + Buffer = A_MALLOC(LINE_SIZE_MAX + 1); + if(NULL == Buffer) { + return A_ERROR; + } + if (FileFormat == MB_FILEFORMAT_PATCH) + { + int LineRead = 0; + while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL) + { + + SKIP_BLANKS(pCharLine); + + // Comment line or empty line + if ((pCharLine[0] == '/') && (pCharLine[1] == '/')) + { + continue; + } + + if ((pCharLine[0] == '#')) { + if (stReadStatus.uSection != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + else { + stReadStatus.uSection = 1; + continue; + } + } + if ((pCharLine[0] == '/') && (pCharLine[1] == '*')) + { + pCharLine+=2; + SKIP_BLANKS(pCharLine); + + if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2)) + ParseSection=RAM_PATCH_SECTION; + + if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2)) + ParseSection=RAM_DYN_MEM_SECTION; + + if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2)) + ParseSection=RAM_PS_SECTION; + + LineRead = 0; + stReadStatus.uSection = 0; + + continue; + } + + switch(ParseSection) + { + case RAM_PS_SECTION: + { + if (stReadStatus.uSection == 1) //TagID + { + SKIP_BLANKS(pCharLine); + if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId)); + + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId); + if (TagCount == 0) + { + StartTagId = PsTagEntry[TagCount].TagId; + } + stReadStatus.uSection = 2; + } + else if (stReadStatus.uSection == 2) //TagLength + { + + if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat); + + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount)); + if (ByteCount > LINE_SIZE_MAX/2) + { + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + PsTagEntry[TagCount].TagLen = ByteCount; + PsTagEntry[TagCount].TagData = (u8 *)A_MALLOC(ByteCount); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount)); + stReadStatus.uSection = 3; + stReadStatus.uLineCount = 0; + } + else if( stReadStatus.uSection == 3) { //Data + + if(stReadStatus.uLineCount == 0) { + if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + } + SKIP_BLANKS(pCharLine); + stReadStatus.uCharCount = 0; + if(pCharLine[stReadStatus.uCharCount] == '[') { + while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) { + stReadStatus.uCharCount++; + } + if(pCharLine[stReadStatus.uCharCount] == ']' ) { + stReadStatus.uCharCount++; + } else { + stReadStatus.uCharCount = 0; + } + } + uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount; + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ")); + if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) { + while(uReadCount > 0) { + PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] = + (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4) + | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1])); + + PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] = + (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4) + | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4])); + + stReadStatus.uCharCount += 6; // read two bytes, plus a space; + stReadStatus.uByteCount += 2; + uReadCount -= 2; + } + if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) { + ByteCount -= BYTES_OF_PS_DATA_PER_LINE; + } + else { + ByteCount = 0; + } + } + else { + //to be implemented + } + + stReadStatus.uLineCount++; + + if(ByteCount == 0) { + stReadStatus.uSection = 0; + stReadStatus.uCharCount = 0; + stReadStatus.uLineCount = 0; + stReadStatus.uByteCount = 0; + } + else { + stReadStatus.uCharCount = 0; + } + + if((stReadStatus.uSection == 0)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + //Sleep (3000); + //exit(1); + } + + } + } + + break; + default: + { + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + break; + } + LineRead++; + } + Tag_Count = TagCount; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count)); + } + + + if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE) + { + + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + + if(Buffer != NULL) { + kfree(Buffer); + } + return 0; + +} + + + +/********************/ + + +int GetNextTwoChar(u8 *srcbuffer,u32 len, u32 *pos, char *buffer) +{ + unsigned char ch; + + ch = AthReadChar(srcbuffer,len,pos); + if(ch != '\0' && isxdigit(ch)) { + buffer[0] = ch; + } else + { + return A_ERROR; + } + ch = AthReadChar(srcbuffer,len,pos); + if(ch != '\0' && isxdigit(ch)) { + buffer[1] = ch; + } else + { + return A_ERROR; + } + return 0; +} + +int AthDoParsePatch(u8 *patchbuffer, u32 patchlen) +{ + + char Byte[3]; + char Line[MAX_BYTE_LENGTH + 1]; + int ByteCount,ByteCount_Org; + int count; + int i,j,k; + int data; + u32 filepos; + Byte[2] = '\0'; + j = 0; + filepos = 0; + Patch_Count = 0; + + while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) { + if(strlen(Line) <= 1 || !isxdigit(Line[0])) { + continue; + } else { + break; + } + } + ByteCount = A_STRTOL(Line, NULL, 16); + ByteCount_Org = ByteCount; + + while(ByteCount > MAX_BYTE_LENGTH){ + + /* Handle case when the number of patch buffer is more than the 20K */ + if(MAX_NUM_PATCH_ENTRY == Patch_Count) { + for(i = 0; i < Patch_Count; i++) { + kfree(RamPatch[i].Data); + } + return A_ERROR; + } + RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH; + RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(MAX_BYTE_LENGTH); + Patch_Count ++; + + + ByteCount= ByteCount - MAX_BYTE_LENGTH; + } + + RamPatch[Patch_Count].Len= (ByteCount & 0xFF); + if(ByteCount != 0) { + RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(ByteCount); + Patch_Count ++; + } + count = 0; + while(ByteCount_Org > MAX_BYTE_LENGTH){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); + for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) { + if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { + return A_ERROR; + } + data = A_STRTOUL(&Byte[0], NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + + + } + j++; + ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH; + } + if(j == 0){ + j++; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); + for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) { + if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { + return A_ERROR; + } + data = A_STRTOUL(Byte, NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + + + } + return 0; +} + + +/********************/ +int AthDoParsePS(u8 *srcbuffer, u32 srclen) +{ + int status; + int i; + bool BDADDR_Present = false; + + Tag_Count = 0; + + Total_tag_lenght = 0; + BDADDR = false; + + + status = A_ERROR; + + if(NULL != srcbuffer && srclen != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n")); + + status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH); + } + + + + if(Tag_Count == 0){ + Total_tag_lenght = 10; + + } + else{ + for(i=0; i 0 && !BDADDR_Present){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is not present adding 10 extra bytes \r\n")); + Total_tag_lenght=Total_tag_lenght + 10; + } + Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght)); + + + return status; +} +char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos) +{ + + int count; + static short flag; + char CharRead; + count = 0; + flag = A_ERROR; + + do + { + CharRead = AthReadChar(srcbuffer,len,pos); + if( CharRead == '\0' ) { + buffer[count+1] = '\0'; + if(count == 0) { + return NULL; + } + else { + return buffer; + } + } + + if(CharRead == 13) { + } else if(CharRead == 10) { + buffer[count] ='\0'; + flag = A_ERROR; + return buffer; + }else { + buffer[count++] = CharRead; + } + + } + while(count < maxlen-1 && CharRead != '\0'); + buffer[count] = '\0'; + + return buffer; +} + +static void LoadHeader(u8 *HCI_PS_Command,u8 opcode,int length,int index){ + + HCI_PS_Command[0]= 0x0B; + HCI_PS_Command[1]= 0xFC; + HCI_PS_Command[2]= length + 4; + HCI_PS_Command[3]= opcode; + HCI_PS_Command[4]= (index & 0xFF); + HCI_PS_Command[5]= ((index>>8) & 0xFF); + HCI_PS_Command[6]= length; +} + +///////////////////////// +// +int AthCreateCommandList(struct ps_cmd_packet **HciPacketList, u32 *numPackets) +{ + + u8 count; + u32 NumcmdEntry = 0; + + u32 Crc = 0; + *numPackets = 0; + + + if(Patch_Count > 0) + Crc |= RAM_PATCH_REGION; + if(Tag_Count > 0) + Crc |= RAM_PS_REGION; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d Tag Count %d \n",Crc,Patch_Count,Tag_Count)); + + if(Patch_Count || Tag_Count ){ + NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet + Patch List + PS List*/ + if(Patch_Count > 0) { + NumcmdEntry++; /* Patch Enable Command */ + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size %d \r\n",NumcmdEntry,(u32)sizeof(struct ps_cmd_packet) * NumcmdEntry)); + (*HciPacketList) = A_MALLOC(sizeof(struct ps_cmd_packet) * NumcmdEntry); + if(NULL == *HciPacketList) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed \r\n")); + } + AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets); + if(Patch_Count > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n")); + AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n")); + AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** %d[0x%x] \r\n",PS_RAM_SIZE,PS_RAM_SIZE)); + AthPSCreateHCICommand(PS_RESET,PS_RAM_SIZE,*HciPacketList,numPackets); + if(Tag_Count > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n")); + AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets); + } + } + if(!BDADDR){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n")); + + } + for(count = 0; count < Patch_Count; count++) { + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing Patch Buffer %d \r\n",count)); + kfree(RamPatch[Patch_Count].Data); + } + + for(count = 0; count < Tag_Count; count++) { + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing PS Buffer %d \r\n",count)); + kfree(PsTagEntry[count].TagData); + } + +/* + * SDIO Transport uses synchronous mode of data transfer + * So, AthPSOperations() call returns only after receiving the + * command complete event. + */ + return *numPackets; +} + + +//////////////////////// + +///////////// +static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index) +{ + u8 *HCI_PS_Command; + u32 Length; + int i,j; + + switch(Opcode) + { + case WRITE_PATCH: + + + for(i=0;i< Param1;i++){ + + HCI_PS_Command = (u8 *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER)); + if(HCI_PS_Command == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); + return A_ERROR; + } + memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER); + LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i); + for(j=0;j> 8) & 0xFF); + PSPatchPacket[*index].Hcipacket = HCI_PS_Command; + PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER; + (*index)++; + + break; + + case PS_WRITE: + for(i=0;i< Param1;i++){ + if(PsTagEntry[i].TagId ==1) + BDADDR = true; + + HCI_PS_Command = (u8 *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); + if(HCI_PS_Command == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); + return A_ERROR; + } + + memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); + LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId); + + for(j=0;j +#include +#include "athdefs.h" +#ifdef HCI_TRANSPORT_SDIO +#include "a_config.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "common_drv.h" +#include "hci_transport_api.h" +#include "ar3kconfig.h" +#else +#ifndef A_PRINTF +#define A_PRINTF(args...) printk(KERN_ALERT args) +#endif /* A_PRINTF */ +#include "debug_linux.h" + +/* Helper data type declaration */ + +#define ATH_DEBUG_ERR (1 << 0) +#define ATH_DEBUG_WARN (1 << 1) +#define ATH_DEBUG_INFO (1 << 2) + + + +#define false 0 +#define true 1 + +#ifndef A_MALLOC +#define A_MALLOC(size) kmalloc((size),GFP_KERNEL) +#endif /* A_MALLOC */ +#endif /* HCI_TRANSPORT_UART */ + +/* String manipulation APIs */ +#ifndef A_STRTOUL +#define A_STRTOUL simple_strtoul +#endif /* A_STRTOL */ + +#ifndef A_STRTOL +#define A_STRTOL simple_strtol +#endif /* A_STRTOL */ + + +/* The maximum number of bytes possible in a patch entry */ +#define MAX_PATCH_SIZE 20000 + +/* Maximum HCI packets that will be formed from the Patch file */ +#define MAX_NUM_PATCH_ENTRY (MAX_PATCH_SIZE/MAX_BYTE_LENGTH) + 1 + + + + + + + +struct ps_cmd_packet +{ + u8 *Hcipacket; + int packetLen; +}; + +/* Parses a Patch information buffer and store it in global structure */ +int AthDoParsePatch(u8 *, u32 ); + +/* parses a PS information buffer and stores it in a global structure */ +int AthDoParsePS(u8 *, u32 ); + +/* + * Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with + * all the PS and patch commands. + * The list will have the below mentioned commands in order. + * CRC command packet + * Download patch command(s) + * Enable patch Command + * PS Reset Command + * PS Tag Command(s) + * + */ +int AthCreateCommandList(struct ps_cmd_packet **, u32 *); + +/* Cleanup the dynamically allicated HCI command list */ +int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets); +#endif /* __AR3KPSPARSER_H */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c b/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c new file mode 100644 index 000000000000..1ce539aa019b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c @@ -0,0 +1,910 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" + +#include "hw/mbox_host_reg.h" +#include "gpio_reg.h" +#include "hw/rtc_reg.h" +#include "hw/mbox_reg.h" +#include "hw/apb_map.h" + +#include "a_osapi.h" +#include "targaddrs.h" +#include "hif.h" +#include "htc_api.h" +#include "wmi.h" +#include "bmi.h" +#include "bmi_msg.h" +#include "common_drv.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "ar6000_diag.h" + +static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL; +static A_MUTEX_T g_ModuleListLock; +static bool g_ModuleDebugInit = false; + +#ifdef ATH_DEBUG_MODULE + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc, + "misc", + "Common and misc APIs", + ATH_DEBUG_MASK_DEFAULTS, + 0, + NULL); + +#endif + +#define HOST_INTEREST_ITEM_ADDRESS(target, item) \ + ((((target) == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((target) == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))) + + +#define AR6001_LOCAL_COUNT_ADDRESS 0x0c014080 +#define AR6002_LOCAL_COUNT_ADDRESS 0x00018080 +#define AR6003_LOCAL_COUNT_ADDRESS 0x00018080 +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_ADDRESS 0x00000484 + +static u8 custDataAR6002[AR6002_CUST_DATA_SIZE]; +static u8 custDataAR6003[AR6003_CUST_DATA_SIZE]; + +/* Compile the 4BYTE version of the window register setup routine, + * This mitigates host interconnect issues with non-4byte aligned bus requests, some + * interconnects use bus adapters that impose strict limitations. + * Since diag window access is not intended for performance critical operations, the 4byte mode should + * be satisfactory even though it generates 4X the bus activity. */ + +#ifdef USE_4BYTE_REGISTER_ACCESS + + /* set the window address register (using 4-byte register access ). */ +int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address) +{ + int status; + u8 addrValue[4]; + s32 i; + + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written + * last to initiate the access cycle */ + + for (i = 1; i <= 3; i++) { + /* fill the buffer with the address byte value we want to hit 4 times*/ + addrValue[0] = ((u8 *)&Address)[i]; + addrValue[1] = addrValue[0]; + addrValue[2] = addrValue[0]; + addrValue[3] = addrValue[0]; + + /* hit each byte of the register address with a 4-byte write operation to the same address, + * this is a harmless operation */ + status = HIFReadWrite(hifDevice, + RegisterAddr+i, + addrValue, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + if (status) { + break; + } + } + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } + + /* write the address register again, this time write the whole 4-byte value. + * The effect here is that the LSB write causes the cycle to start, the extra + * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */ + status = HIFReadWrite(hifDevice, + RegisterAddr, + (u8 *)(&Address), + 4, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } + + return 0; + + + +} + + +#else + + /* set the window address register */ +int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address) +{ + int status; + + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written + * last to initiate the access cycle */ + status = HIFReadWrite(hifDevice, + RegisterAddr+1, /* write upper 3 bytes */ + ((u8 *)(&Address))+1, + sizeof(u32)-1, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", + RegisterAddr, Address)); + return status; + } + + /* write the LSB of the register, this initiates the operation */ + status = HIFReadWrite(hifDevice, + RegisterAddr, + (u8 *)(&Address), + sizeof(u8), + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", + RegisterAddr, Address)); + return status; + } + + return 0; +} + +#endif + +/* + * Read from the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +int +ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data) +{ + int status; + + /* set window register to start read cycle */ + status = ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_READ_ADDR_ADDRESS, + *address); + + if (status) { + return status; + } + + /* read the data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (u8 *)data, + sizeof(u32), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n")); + return status; + } + + return status; +} + + +/* + * Write to the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +int +ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data) +{ + int status; + + /* set write data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (u8 *)data, + sizeof(u32), + HIF_WR_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data)); + return status; + } + + /* set window register, which starts the write cycle */ + return ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_WRITE_ADDR_ADDRESS, + *address); + } + +int +ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length) +{ + u32 count; + int status = 0; + + for (count = 0; count < length; count += 4, address += 4) { + if ((status = ar6000_ReadRegDiag(hifDevice, &address, + (u32 *)&data[count])) != 0) + { + break; + } + } + + return status; +} + +int +ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length) +{ + u32 count; + int status = 0; + + for (count = 0; count < length; count += 4, address += 4) { + if ((status = ar6000_WriteRegDiag(hifDevice, &address, + (u32 *)&data[count])) != 0) + { + break; + } + } + + return status; +} + +int +ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval) +{ + int status; + u8 vals[4]; + u8 register_selection[4]; + + register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff); + status = HIFReadWrite(hifDevice, + CPU_DBG_SEL_ADDRESS, + register_selection, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel)); + return status; + } + + status = HIFReadWrite(hifDevice, + CPU_DBG_ADDRESS, + (u8 *)vals, + sizeof(vals), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n")); + return status; + } + + *regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24; + + return status; +} + +void +ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs) +{ + int i; + u32 val; + + for (i=0; i REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6001 too large" +#endif +#if REG_DUMP_COUNT_AR6002 > REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6002 too large" +#endif +#if REG_DUMP_COUNT_AR6003 > REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6003 too large" +#endif + + +void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType) +{ + u32 address; + u32 regDumpArea = 0; + int status; + u32 regDumpValues[REGISTER_DUMP_LEN_MAX]; + u32 regDumpCount = 0; + u32 i; + + do { + + /* the reg dump pointer is copied to the host interest area */ + address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state); + address = TARG_VTOP(TargetType, address); + + if (TargetType == TARGET_TYPE_AR6002) { + regDumpCount = REG_DUMP_COUNT_AR6002; + } else if (TargetType == TARGET_TYPE_AR6003) { + regDumpCount = REG_DUMP_COUNT_AR6003; + } else { + A_ASSERT(0); + } + + /* read RAM location through diagnostic window */ + status = ar6000_ReadRegDiag(hifDevice, &address, ®DumpArea); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea)); + + if (regDumpArea == 0) { + /* no reg dump */ + break; + } + + regDumpArea = TARG_VTOP(TargetType, regDumpArea); + + /* fetch register dump data */ + status = ar6000_ReadDataDiag(hifDevice, + regDumpArea, + (u8 *)®DumpValues[0], + regDumpCount * (sizeof(u32))); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n")); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n")); + + for (i = 0; i < regDumpCount; i++) { + //ATHR_DISPLAY_MSG (_T(" %d : 0x%8.8X \n"), i, regDumpValues[i]); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i])); + +#ifdef UNDER_CE + /* + * For Every logPrintf() Open the File so that in case of Crashes + * We will have until the Last Message Flushed on to the File + * So use logPrintf Sparingly..!! + */ + tgtassertPrintf (ATH_DEBUG_TRC," %d: 0x%8.8X \n",i, regDumpValues[i]); +#endif + } + + } while (false); + +} + +/* set HTC/Mbox operational parameters, this can only be called when the target is in the + * BMI phase */ +int ar6000_set_htc_params(struct hif_device *hifDevice, + u32 TargetType, + u32 MboxIsrYieldValue, + u8 HtcControlBuffers) +{ + int status; + u32 blocksizes[HTC_MAILBOX_NUM_MAX]; + + do { + /* get the block sizes */ + status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n")); + break; + } + /* note: we actually get the block size for mailbox 1, for SDIO the block + * size on mailbox 0 is artificially set to 1 */ + /* must be a power of 2 */ + A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); + + if (HtcControlBuffers != 0) { + /* set override for number of control buffers to use */ + blocksizes[1] |= ((u32)HtcControlBuffers) << 16; + } + + /* set the host interest area for the block size */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz), + (u8 *)&blocksizes[1], + 4); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n", + blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz))); + + if (MboxIsrYieldValue != 0) { + /* set the host interest area for the mbox ISR yield limit */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit), + (u8 *)&MboxIsrYieldValue, + 4); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n")); + break; + } + } + + } while (false); + + return status; +} + +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription) +{ + char stream[60]; + char byteOffsetStr[10]; + u32 i; + u16 offset, count, byteOffset; + + A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription); + + count = 0; + offset = 0; + byteOffset = 0; + for(i = 0; i < length; i++) { + A_SPRINTF(stream + offset, "%2.2X ", buffer[i]); + count ++; + offset += 3; + + if(count == 16) { + count = 0; + offset = 0; + A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + A_MEMZERO(stream, 60); + byteOffset += 16; + } + } + + if(offset != 0) { + A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + } + + A_PRINTF("<------------------------------------------------->\n"); +} + +void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) +{ + int i; + struct ath_debug_mask_description *pDesc; + + if (pInfo == NULL) { + return; + } + + pDesc = pInfo->pMaskDescriptions; + + A_PRINTF("========================================================\n\n"); + A_PRINTF("Module Debug Info => Name : %s \n", pInfo->ModuleName); + A_PRINTF(" => Descr. : %s \n", pInfo->ModuleDescription); + A_PRINTF("\n Current mask => 0x%8.8X \n", pInfo->CurrentMask); + A_PRINTF("\n Avail. Debug Masks :\n\n"); + + for (i = 0; i < pInfo->MaxDescriptions; i++,pDesc++) { + A_PRINTF(" => 0x%8.8X -- %s \n", pDesc->Mask, pDesc->Description); + } + + if (0 == i) { + A_PRINTF(" => * none defined * \n"); + } + + A_PRINTF("\n Standard Debug Masks :\n\n"); + /* print standard masks */ + A_PRINTF(" => 0x%8.8X -- Errors \n", ATH_DEBUG_ERR); + A_PRINTF(" => 0x%8.8X -- Warnings \n", ATH_DEBUG_WARN); + A_PRINTF(" => 0x%8.8X -- Informational \n", ATH_DEBUG_INFO); + A_PRINTF(" => 0x%8.8X -- Tracing \n", ATH_DEBUG_TRC); + A_PRINTF("\n========================================================\n"); + +} + + +static ATH_DEBUG_MODULE_DBG_INFO *FindModule(char *module_name) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + + if (!g_ModuleDebugInit) { + return NULL; + } + + while (pInfo != NULL) { + /* TODO: need to use something other than strlen */ + if (memcmp(pInfo->ModuleName,module_name,strlen(module_name)) == 0) { + break; + } + pInfo = pInfo->pNext; + } + + return pInfo; +} + + +void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) +{ + if (!g_ModuleDebugInit) { + return; + } + + A_MUTEX_LOCK(&g_ModuleListLock); + + if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) { + if (g_pModuleInfoHead == NULL) { + g_pModuleInfoHead = pInfo; + } else { + pInfo->pNext = g_pModuleInfoHead; + g_pModuleInfoHead = pInfo; + } + pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED; + } + + A_MUTEX_UNLOCK(&g_ModuleListLock); +} + +void a_dump_module_debug_info_by_name(char *module_name) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + + if (!g_ModuleDebugInit) { + return; + } + + if (memcmp(module_name,"all",3) == 0) { + /* dump all */ + while (pInfo != NULL) { + a_dump_module_debug_info(pInfo); + pInfo = pInfo->pNext; + } + return; + } + + pInfo = FindModule(module_name); + + if (pInfo != NULL) { + a_dump_module_debug_info(pInfo); + } + +} + +int a_get_module_mask(char *module_name, u32 *pMask) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); + + if (NULL == pInfo) { + return A_ERROR; + } + + *pMask = pInfo->CurrentMask; + return 0; +} + +int a_set_module_mask(char *module_name, u32 Mask) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); + + if (NULL == pInfo) { + return A_ERROR; + } + + pInfo->CurrentMask = Mask; + A_PRINTF("Module %s, new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask); + return 0; +} + + +void a_module_debug_support_init(void) +{ + if (g_ModuleDebugInit) { + return; + } + A_MUTEX_INIT(&g_ModuleListLock); + g_pModuleInfoHead = NULL; + g_ModuleDebugInit = true; + A_REGISTER_MODULE_DEBUG_INFO(misc); +} + +void a_module_debug_support_cleanup(void) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + ATH_DEBUG_MODULE_DBG_INFO *pCur; + + if (!g_ModuleDebugInit) { + return; + } + + g_ModuleDebugInit = false; + + A_MUTEX_LOCK(&g_ModuleListLock); + + while (pInfo != NULL) { + pCur = pInfo; + pInfo = pInfo->pNext; + pCur->pNext = NULL; + /* clear registered flag */ + pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED; + } + + A_MUTEX_UNLOCK(&g_ModuleListLock); + + A_MUTEX_DELETE(&g_ModuleListLock); + g_pModuleInfoHead = NULL; +} + + /* can only be called during bmi init stage */ +int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice, + u32 TargetType, + u32 Flags) +{ + int status = 0; + + do { + + if (TargetType != TARGET_TYPE_AR6003) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Target Type:%d, does not support HCI bridging! \n", + TargetType)); + break; + } + + /* set hci bridge flags */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags), + (u8 *)&Flags, + 4); + + + } while (false); + + return status; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c b/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c new file mode 100644 index 000000000000..c777e98a756e --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c @@ -0,0 +1,417 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "htc_api.h" +#include "common_drv.h" + +/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/ + +#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */ +#define CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS 1 + +#ifdef NO_VO_SERVICE +#define DATA_SVCS_USED 3 +#else +#define DATA_SVCS_USED 4 +#endif + +static void RedistributeCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList); + +static void SeekCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList); + +/* reduce an ep's credits back to a set limit */ +static INLINE void ReduceCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEpDist, + int Limit) +{ + int credits; + + /* set the new limit */ + pEpDist->TxCreditsAssigned = Limit; + + if (pEpDist->TxCredits <= Limit) { + return; + } + + /* figure out how much to take away */ + credits = pEpDist->TxCredits - Limit; + /* take them away */ + pEpDist->TxCredits -= credits; + pCredInfo->CurrentFreeCredits += credits; +} + +/* give an endpoint some credits from the free credit pool */ +#define GiveCredits(pCredInfo,pEpDist,credits) \ +{ \ + (pEpDist)->TxCredits += (credits); \ + (pEpDist)->TxCreditsAssigned += (credits); \ + (pCredInfo)->CurrentFreeCredits -= (credits); \ +} + + +/* default credit init callback. + * This function is called in the context of HTCStart() to setup initial (application-specific) + * credit distributions */ +static void ar6000_credit_init(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int count; + struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context; + + pCredInfo->CurrentFreeCredits = TotalCredits; + pCredInfo->TotalAvailableCredits = TotalCredits; + + pCurEpDist = pEPList; + + /* run through the list and initialize */ + while (pCurEpDist != NULL) { + + /* set minimums for each endpoint */ + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + + if (TotalCredits > 4) + { + if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)){ + /* assign at least min credits to lower than VO priority services */ + GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin); + /* force active */ + SET_EP_ACTIVE(pCurEpDist); + } + } + +#endif + + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { + /* give control service some credits */ + GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin); + /* control service is always marked active, it never goes inactive EVER */ + SET_EP_ACTIVE(pCurEpDist); + } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) { + /* this is the lowest priority data endpoint, save this off for easy access */ + pCredInfo->pLowestPriEpDist = pCurEpDist; + } + + /* Streams have to be created (explicit | implicit)for all kinds + * of traffic. BE endpoints are also inactive in the beginning. + * When BE traffic starts it creates implicit streams that + * redistributes credits. + */ + + /* note, all other endpoints have minimums set but are initially given NO credits. + * Credits will be distributed as traffic activity demands */ + pCurEpDist = pCurEpDist->pNext; + } + + if (pCredInfo->CurrentFreeCredits <= 0) { + AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits)); + A_ASSERT(false); + return; + } + + /* reset list */ + pCurEpDist = pEPList; + /* now run through the list and set max operating credit limits for everyone */ + while (pCurEpDist != NULL) { + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { + /* control service max is just 1 max message */ + pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg; + } else { + /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are + * the same. + * We use a simple calculation here, we take the remaining credits and + * determine how many max messages this can cover and then set each endpoint's + * normal value equal to 3/4 this amount. + * */ + count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg; + count = (count * 3) >> 2; + count = max(count,pCurEpDist->TxCreditsPerMaxMsg); + /* set normal */ + pCurEpDist->TxCreditsNorm = count; + + } + pCurEpDist = pCurEpDist->pNext; + } + +} + + +/* default credit distribution callback + * This callback is invoked whenever endpoints require credit distributions. + * A lock is held while this function is invoked, this function shall NOT block. + * The pEPDistList is a list of distribution structures in prioritized order as + * defined by the call to the HTCSetCreditDistribution() api. + * + */ +static void ar6000_credit_distribute(void *Context, + struct htc_endpoint_credit_dist *pEPDistList, + HTC_CREDIT_DIST_REASON Reason) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context; + + switch (Reason) { + case HTC_CREDIT_DIST_SEND_COMPLETE : + pCurEpDist = pEPDistList; + /* we are given the start of the endpoint distribution list. + * There may be one or more endpoints to service. + * Run through the list and distribute credits */ + while (pCurEpDist != NULL) { + + if (pCurEpDist->TxCreditsToDist > 0) { + /* return the credits back to the endpoint */ + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; + /* always zero out when we are done */ + pCurEpDist->TxCreditsToDist = 0; + + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) { + /* reduce to the assigned limit, previous credit reductions + * could have caused the limit to change */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned); + } + + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) { + /* oversubscribed endpoints need to reduce back to normal */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm); + } + + if (!IS_EP_ACTIVE(pCurEpDist)) { + /* endpoint is inactive, now check for messages waiting for credits */ + if (pCurEpDist->TxQueueDepth == 0) { + /* EP is inactive and there are no pending messages, + * reduce credits back to zero to recover credits */ + ReduceCredits(pCredInfo, pCurEpDist, 0); + } + } + } + + pCurEpDist = pCurEpDist->pNext; + } + + break; + + case HTC_CREDIT_DIST_ACTIVITY_CHANGE : + RedistributeCredits(pCredInfo,pEPDistList); + break; + case HTC_CREDIT_DIST_SEEK_CREDITS : + SeekCredits(pCredInfo,pEPDistList); + break; + case HTC_DUMP_CREDIT_STATE : + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Credit Distribution, total : %d, free : %d\n", + pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits)); + break; + default: + break; + + } + + /* sanity checks done after each distribution action */ + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits); + A_ASSERT(pCredInfo->CurrentFreeCredits >= 0); + +} + +/* redistribute credits based on activity change */ +static void RedistributeCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList) +{ + struct htc_endpoint_credit_dist *pCurEpDist = pEPDistList; + + /* walk through the list and remove credits from inactive endpoints */ + while (pCurEpDist != NULL) { + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + + if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)) { + /* force low priority streams to always be active to retain their minimum credit distribution */ + SET_EP_ACTIVE(pCurEpDist); + } +#endif + + if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) { + if (!IS_EP_ACTIVE(pCurEpDist)) { + if (pCurEpDist->TxQueueDepth == 0) { + /* EP is inactive and there are no pending messages, reduce credits back to zero */ + ReduceCredits(pCredInfo, pCurEpDist, 0); + } else { + /* we cannot zero the credits assigned to this EP, but to keep + * the credits available for these leftover packets, reduce to + * a minimum */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsMin); + } + } + } + + /* NOTE in the active case, we do not need to do anything further, + * when an EP goes active and needs credits, HTC will call into + * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */ + + pCurEpDist = pCurEpDist->pNext; + } + +} + +/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */ +static void SeekCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDist) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int credits = 0; + int need; + + do { + + if (pEPDist->ServiceID == WMI_CONTROL_SVC) { + /* we never oversubscribe on the control service, this is not + * a high performance path and the target never holds onto control + * credits for too long */ + break; + } + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + if (pEPDist->ServiceID == WMI_DATA_VI_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) { + /* limit VI service from oversubscribing */ + break; + } + } + + if (pEPDist->ServiceID == WMI_DATA_VO_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) { + /* limit VO service from oversubscribing */ + break; + } + } +#else + if (pEPDist->ServiceID == WMI_DATA_VI_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) || + (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) { + /* limit VI service from oversubscribing */ + /* at least one free credit will not be used by VI */ + break; + } + } + + if (pEPDist->ServiceID == WMI_DATA_VO_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) || + (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) { + /* limit VO service from oversubscribing */ + /* at least one free credit will not be used by VO */ + break; + } + } +#endif + + /* for all other services, we follow a simple algorithm of + * 1. checking the free pool for credits + * 2. checking lower priority endpoints for credits to take */ + + /* give what we can */ + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); + + if (credits >= pEPDist->TxCreditsSeek) { + /* we found some to fulfill the seek request */ + break; + } + + /* we don't have enough in the free pool, try taking away from lower priority services + * + * The rule for taking away credits: + * 1. Only take from lower priority endpoints + * 2. Only take what is allocated above the minimum (never starve an endpoint completely) + * 3. Only take what you need. + * + * */ + + /* starting at the lowest priority */ + pCurEpDist = pCredInfo->pLowestPriEpDist; + + /* work backwards until we hit the endpoint again */ + while (pCurEpDist != pEPDist) { + /* calculate how many we need so far */ + need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits; + + if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsMin) { + /* the current one has been allocated more than it's minimum and it + * has enough credits assigned above it's minimum to fulfill our need + * try to take away just enough to fulfill our need */ + ReduceCredits(pCredInfo, + pCurEpDist, + pCurEpDist->TxCreditsAssigned - need); + + if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) { + /* we have enough */ + break; + } + } + + pCurEpDist = pCurEpDist->pPrev; + } + + /* return what we can get */ + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); + + } while (false); + + /* did we find some credits? */ + if (credits) { + /* give what we can */ + GiveCredits(pCredInfo, pEPDist, credits); + } + +} + +/* initialize and setup credit distribution */ +int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo) +{ + HTC_SERVICE_ID servicepriority[5]; + + A_MEMZERO(pCredInfo,sizeof(struct common_credit_state_info)); + + servicepriority[0] = WMI_CONTROL_SVC; /* highest */ + servicepriority[1] = WMI_DATA_VO_SVC; + servicepriority[2] = WMI_DATA_VI_SVC; + servicepriority[3] = WMI_DATA_BE_SVC; + servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ + + /* set callbacks and priority list */ + HTCSetCreditDistribution(HTCHandle, + pCredInfo, + ar6000_credit_distribute, + ar6000_credit_init, + servicepriority, + 5); + + return 0; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h b/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h new file mode 100644 index 000000000000..41be5670db42 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _MISCDRV_H +#define _MISCDRV_H + + +#define HOST_INTEREST_ITEM_ADDRESS(target, item) \ + AR6002_HOST_INTEREST_ITEM_ADDRESS(item) + +u32 ar6kRev2Array[][128] = { + {0xFFFF, 0xFFFF}, // No Patches + }; + +#define CFG_REV2_ITEMS 0 // no patches so far +#define AR6K_RESET_ADDR 0x4000 +#define AR6K_RESET_VAL 0x100 + +#define EEPROM_SZ 768 +#define EEPROM_WAIT_LIMIT 4 + +#endif + diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c new file mode 100644 index 000000000000..32ee39ad00df --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c @@ -0,0 +1,6267 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +/* + * This driver is a pseudo ethernet driver to access the Atheros AR6000 + * WLAN Device + */ + +#include "ar6000_drv.h" +#include "cfg80211.h" +#include "htc.h" +#include "wmi_filter_linux.h" +#include "epping_test.h" +#include "wlan_config.h" +#include "ar3kconfig.h" +#include "ar6k_pal.h" +#include "AR6002/addrs.h" + + +/* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux behavior. When + * the meta data was added to the header it was found that linux did not correctly provide + * enough headroom. However when more headroom was requested beyond what was truly needed + * Linux gave the requested headroom. Therefore to get the necessary headroom from Linux + * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FACTOR */ +#define LINUX_HACK_FUDGE_FACTOR 16 +#define BDATA_BDADDR_OFFSET 28 + +u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + +#ifdef DEBUG + +#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) +#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) + +static struct ath_debug_mask_description driver_debug_desc[] = { + { ATH_DEBUG_DBG_LOG , "Target Debug Logs"}, + { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"}, + { ATH_DEBUG_WLAN_SCAN , "WLAN scan"}, + { ATH_DEBUG_WLAN_TX , "WLAN Tx"}, + { ATH_DEBUG_WLAN_RX , "WLAN Rx"}, + { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"}, + { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"}, + { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"}, + { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver, + "driver", + "Linux Driver Interface", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN | + ATH_DEBUG_HCI_BRIDGE, + ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc), + driver_debug_desc); + +#endif + + +#define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && mac[4]==0 && mac[5]==0) +#define IS_MAC_BCAST(mac) (*mac==0xff) + +#define DESCRIPTION "Driver to access the Atheros AR600x Device, version " __stringify(__VER_MAJOR_) "." __stringify(__VER_MINOR_) "." __stringify(__VER_PATCH_) "." __stringify(__BUILD_NUMBER_) + +MODULE_AUTHOR("Atheros Communications, Inc."); +MODULE_DESCRIPTION(DESCRIPTION); +MODULE_LICENSE("Dual BSD/GPL"); + +#ifndef REORG_APTC_HEURISTICS +#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL +#endif /* REORG_APTC_HEURISTICS */ + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */ +#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */ +#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */ + +typedef struct aptc_traffic_record { + bool timerScheduled; + struct timeval samplingTS; + unsigned long bytesReceived; + unsigned long bytesTransmitted; +} APTC_TRAFFIC_RECORD; + +A_TIMER aptcTimer; +APTC_TRAFFIC_RECORD aptcTR; +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +// callbacks registered by HCI transport driver +struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL }; +#endif + +unsigned int processDot11Hdr = 0; + +char ifname[IFNAMSIZ] = {0,}; + +int wlaninitmode = WLAN_INIT_MODE_DEFAULT; +static bool bypasswmi; +unsigned int debuglevel = 0; +int tspecCompliance = ATHEROS_COMPLIANCE; +unsigned int busspeedlow = 0; +unsigned int onebitmode = 0; +unsigned int skipflash = 0; +unsigned int wmitimeout = 2; +unsigned int wlanNodeCaching = 1; +unsigned int enableuartprint = ENABLEUARTPRINT_DEFAULT; +unsigned int logWmiRawMsgs = 0; +unsigned int enabletimerwar = 0; +unsigned int num_device = 1; +unsigned int regscanmode; +unsigned int fwmode = 1; +unsigned int mbox_yield_limit = 99; +unsigned int enablerssicompensation = 0; +int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF; +int allow_trace_signal = 0; +#ifdef CONFIG_HOST_TCMD_SUPPORT +unsigned int testmode =0; +#endif + +unsigned int irqprocmode = HIF_DEVICE_IRQ_SYNC_ONLY;//HIF_DEVICE_IRQ_ASYNC_SYNC; +unsigned int panic_on_assert = 1; +unsigned int nohifscattersupport = NOHIFSCATTERSUPPORT_DEFAULT; + +unsigned int setuphci = SETUPHCI_DEFAULT; +unsigned int loghci = 0; +unsigned int setupbtdev = SETUPBTDEV_DEFAULT; +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +unsigned int ar3khcibaud = AR3KHCIBAUD_DEFAULT; +unsigned int hciuartscale = HCIUARTSCALE_DEFAULT; +unsigned int hciuartstep = HCIUARTSTEP_DEFAULT; +#endif +unsigned int csumOffload=0; +unsigned int csumOffloadTest=0; +unsigned int eppingtest=0; +unsigned int mac_addr_method; +unsigned int firmware_bridge; + +module_param_string(ifname, ifname, sizeof(ifname), 0644); +module_param(wlaninitmode, int, 0644); +module_param(bypasswmi, bool, 0644); +module_param(debuglevel, uint, 0644); +module_param(tspecCompliance, int, 0644); +module_param(onebitmode, uint, 0644); +module_param(busspeedlow, uint, 0644); +module_param(skipflash, uint, 0644); +module_param(wmitimeout, uint, 0644); +module_param(wlanNodeCaching, uint, 0644); +module_param(logWmiRawMsgs, uint, 0644); +module_param(enableuartprint, uint, 0644); +module_param(enabletimerwar, uint, 0644); +module_param(fwmode, uint, 0644); +module_param(mbox_yield_limit, uint, 0644); +module_param(reduce_credit_dribble, int, 0644); +module_param(allow_trace_signal, int, 0644); +module_param(enablerssicompensation, uint, 0644); +module_param(processDot11Hdr, uint, 0644); +module_param(csumOffload, uint, 0644); +#ifdef CONFIG_HOST_TCMD_SUPPORT +module_param(testmode, uint, 0644); +#endif +module_param(irqprocmode, uint, 0644); +module_param(nohifscattersupport, uint, 0644); +module_param(panic_on_assert, uint, 0644); +module_param(setuphci, uint, 0644); +module_param(loghci, uint, 0644); +module_param(setupbtdev, uint, 0644); +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +module_param(ar3khcibaud, uint, 0644); +module_param(hciuartscale, uint, 0644); +module_param(hciuartstep, uint, 0644); +#endif +module_param(eppingtest, uint, 0644); + +/* in 2.6.10 and later this is now a pointer to a uint */ +unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX; +#define mboxnum &_mboxnum + +#ifdef DEBUG +u32 g_dbg_flags = DBG_DEFAULTS; +unsigned int debugflags = 0; +int debugdriver = 0; +unsigned int debughtc = 0; +unsigned int debugbmi = 0; +unsigned int debughif = 0; +unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0}; +module_param(debugflags, uint, 0644); +module_param(debugdriver, int, 0644); +module_param(debughtc, uint, 0644); +module_param(debugbmi, uint, 0644); +module_param(debughif, uint, 0644); +module_param_array(txcreditsavailable, uint, mboxnum, 0644); +module_param_array(txcreditsconsumed, uint, mboxnum, 0644); +module_param_array(txcreditintrenable, uint, mboxnum, 0644); +module_param_array(txcreditintrenableaggregate, uint, mboxnum, 0644); + +#endif /* DEBUG */ + +unsigned int resetok = 1; +unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int hifBusRequestNumMax = 40; +unsigned int war23838_disabled = 0; +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +unsigned int enableAPTCHeuristics = 1; +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ +module_param_array(tx_attempt, uint, mboxnum, 0644); +module_param_array(tx_post, uint, mboxnum, 0644); +module_param_array(tx_complete, uint, mboxnum, 0644); +module_param(hifBusRequestNumMax, uint, 0644); +module_param(war23838_disabled, uint, 0644); +module_param(resetok, uint, 0644); +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +module_param(enableAPTCHeuristics, uint, 0644); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +#ifdef BLOCK_TX_PATH_FLAG +int blocktx = 0; +module_param(blocktx, int, 0644); +#endif /* BLOCK_TX_PATH_FLAG */ + +typedef struct user_rssi_compensation_t { + u16 customerID; + union { + u16 a_enable; + u16 bg_enable; + u16 enable; + }; + s16 bg_param_a; + s16 bg_param_b; + s16 a_param_a; + s16 a_param_b; + u32 reserved; +} USER_RSSI_CPENSATION; + +static USER_RSSI_CPENSATION rssi_compensation_param; + +static s16 rssi_compensation_table[96]; + +int reconnect_flag = 0; +static ar6k_pal_config_t ar6k_pal_config_g; + +/* Function declarations */ +static int ar6000_init_module(void); +static void ar6000_cleanup_module(void); + +int ar6000_init(struct net_device *dev); +static int ar6000_open(struct net_device *dev); +static int ar6000_close(struct net_device *dev); +static void ar6000_init_control_info(struct ar6_softc *ar); +static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev); + +void ar6000_destroy(struct net_device *dev, unsigned int unregister); +static void ar6000_detect_error(unsigned long ptr); +static void ar6000_set_multicast_list(struct net_device *dev); +static struct net_device_stats *ar6000_get_stats(struct net_device *dev); + +static void disconnect_timer_handler(unsigned long ptr); + +void read_rssi_compensation_param(struct ar6_softc *ar); + +/* + * HTC service connection handlers + */ +static int ar6000_avail_ev(void *context, void *hif_handle); + +static int ar6000_unavail_ev(void *context, void *hif_handle); + +int ar6000_configure_target(struct ar6_softc *ar); + +static void ar6000_target_failure(void *Instance, int Status); + +static void ar6000_rx(void *Context, struct htc_packet *pPacket); + +static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint); + +static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets); + +static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket); + +static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num); +static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf); +//static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf); + +static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length); + +static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count); + +static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar); + +static ssize_t +ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count); + +static ssize_t +ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count); + +static int +ar6000_sysfs_bmi_init(struct ar6_softc *ar); + +void ar6k_cleanup_hci_pal(struct ar6_softc *ar); + +static void +ar6000_sysfs_bmi_deinit(struct ar6_softc *ar); + +int +ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode); + +/* + * Static variables + */ + +struct net_device *ar6000_devices[MAX_AR6000]; +static int is_netdev_registered; +DECLARE_WAIT_QUEUE_HEAD(arEvent); +static void ar6000_cookie_init(struct ar6_softc *ar); +static void ar6000_cookie_cleanup(struct ar6_softc *ar); +static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie); +static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar); + +static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl); + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +struct net_device *arApNetDev; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM]; + +#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ + (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) + + +static struct net_device_ops ar6000_netdev_ops = { + .ndo_init = NULL, + .ndo_open = ar6000_open, + .ndo_stop = ar6000_close, + .ndo_get_stats = ar6000_get_stats, + .ndo_start_xmit = ar6000_data_tx, + .ndo_set_multicast_list = ar6000_set_multicast_list, +}; + +/* Debug log support */ + +/* + * Flag to govern whether the debug logs should be parsed in the kernel + * or reported to the application. + */ +#define REPORT_DEBUG_LOGS_TO_APP + +int +ar6000_set_host_app_area(struct ar6_softc *ar) +{ + u32 address, data; + struct host_app_area_s host_app_area; + + /* Fetch the address of the host_app_area_s instance in the host interest area */ + address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest)); + if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) { + return A_ERROR; + } + address = TARG_VTOP(ar->arTargetType, data); + host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; + if (ar6000_WriteDataDiag(ar->arHifDevice, address, + (u8 *)&host_app_area, + sizeof(struct host_app_area_s)) != 0) + { + return A_ERROR; + } + + return 0; +} + +u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar) +{ + u32 param; + u32 address; + int status; + + address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr)); + if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)¶m, 4)) != 0) + { + param = 0; + } + + return param; +} + +/* + * The dbglog module has been initialized. Its ok to access the relevant + * data stuctures over the diagnostic window. + */ +void +ar6000_dbglog_init_done(struct ar6_softc *ar) +{ + ar->dbglog_init_done = true; +} + +u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit) +{ + s32 *buffer; + u32 count; + u32 numargs; + u32 length; + u32 fraglen; + + count = fraglen = 0; + buffer = (s32 *)datap; + length = (limit >> 2); + + if (len <= limit) { + fraglen = len; + } else { + while (count < length) { + numargs = DBGLOG_GET_NUMARGS(buffer[count]); + fraglen = (count << 2); + count += numargs + 1; + } + } + + return fraglen; +} + +void +dbglog_parse_debug_logs(s8 *datap, u32 len) +{ + s32 *buffer; + u32 count; + u32 timestamp; + u32 debugid; + u32 moduleid; + u32 numargs; + u32 length; + + count = 0; + buffer = (s32 *)datap; + length = (len >> 2); + while (count < length) { + debugid = DBGLOG_GET_DBGID(buffer[count]); + moduleid = DBGLOG_GET_MODULEID(buffer[count]); + numargs = DBGLOG_GET_NUMARGS(buffer[count]); + timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]); + switch (numargs) { + case 0: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid, timestamp)); + break; + + case 1: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, debugid, + timestamp, buffer[count+1])); + break; + + case 2: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid, + timestamp, buffer[count+1], buffer[count+2])); + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs)); + } + count += numargs + 1; + } +} + +int +ar6000_dbglog_get_debug_logs(struct ar6_softc *ar) +{ + u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */ + u32 address; + u32 length; + u32 dropped; + u32 firstbuf; + u32 debug_hdr_ptr; + + if (!ar->dbglog_init_done) return A_ERROR; + + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (ar->dbgLogFetchInProgress) { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + return A_EBUSY; + } + + /* block out others */ + ar->dbgLogFetchInProgress = true; + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar); + printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr); + + /* Get the contents of the ring buffer */ + if (debug_hdr_ptr) { + address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr); + length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */; + A_MEMZERO(data, sizeof(data)); + ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length); + address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */); + firstbuf = address; + dropped = data[1]; /* dropped */ + length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; + A_MEMZERO(data, sizeof(data)); + ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length); + + do { + address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/); + length = data[3]; /* length */ + if ((length) && (length <= data[2] /* bufsize*/)) { + /* Rewind the index if it is about to overrun the buffer */ + if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) { + ar->log_cnt = 0; + } + if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)&ar->log_buffer[ar->log_cnt], length)) + { + break; + } + ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length); + ar->log_cnt += length; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n", + data[3], data[2])); + } + + address = TARG_VTOP(ar->arTargetType, data[0] /* next */); + length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; + A_MEMZERO(data, sizeof(data)); + if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)&data, length)) + { + break; + } + + } while (address != firstbuf); + } + + ar->dbgLogFetchInProgress = false; + + return 0; +} + +void +ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, + s8 *buffer, u32 length) +{ +#ifdef REPORT_DEBUG_LOGS_TO_APP + #define MAX_WIRELESS_EVENT_SIZE 252 + /* + * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages. + * There seems to be a limitation on the length of message that could be + * transmitted to the user app via this mechanism. + */ + u32 send, sent; + + sent = 0; + send = dbglog_get_debug_fragment(&buffer[sent], length - sent, + MAX_WIRELESS_EVENT_SIZE); + while (send) { + sent += send; + send = dbglog_get_debug_fragment(&buffer[sent], length - sent, + MAX_WIRELESS_EVENT_SIZE); + } +#else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n", + dropped, length)); + + /* Interpret the debug logs */ + dbglog_parse_debug_logs((s8 *)buffer, length); +#endif /* REPORT_DEBUG_LOGS_TO_APP */ +} + + +static int __init +ar6000_init_module(void) +{ + static int probed = 0; + int r; + OSDRV_CALLBACKS osdrvCallbacks; + + a_module_debug_support_init(); + +#ifdef DEBUG + /* check for debug mask overrides */ + if (debughtc != 0) { + ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc); + } + if (debugbmi != 0) { + ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi); + } + if (debughif != 0) { + ATH_DEBUG_SET_DEBUG_MASK(hif,debughif); + } + if (debugdriver != 0) { + ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver); + } + +#endif + + A_REGISTER_MODULE_DEBUG_INFO(driver); + + A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks)); + osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev; + osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev; +#ifdef CONFIG_PM + osdrvCallbacks.deviceSuspendHandler = ar6000_suspend_ev; + osdrvCallbacks.deviceResumeHandler = ar6000_resume_ev; + osdrvCallbacks.devicePowerChangeHandler = ar6000_power_change_ev; +#endif + +#ifdef DEBUG + /* Set the debug flags if specified at load time */ + if(debugflags != 0) + { + g_dbg_flags = debugflags; + } +#endif + + if (probed) { + return -ENODEV; + } + probed++; + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD)); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + r = HIFInit(&osdrvCallbacks); + if (r) + return r; + + return 0; +} + +static void __exit +ar6000_cleanup_module(void) +{ + int i = 0; + struct net_device *ar6000_netdev; + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + /* Delete the Adaptive Power Control timer */ + if (timer_pending(&aptcTimer)) { + del_timer_sync(&aptcTimer); + } +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + for (i=0; i < MAX_AR6000; i++) { + if (ar6000_devices[i] != NULL) { + ar6000_netdev = ar6000_devices[i]; + ar6000_devices[i] = NULL; + ar6000_destroy(ar6000_netdev, 1); + } + } + + HIFShutDownDevice(NULL); + + a_module_debug_support_cleanup(); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n")); +} + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +void +aptcTimerHandler(unsigned long arg) +{ + u32 numbytes; + u32 throughput; + struct ar6_softc *ar; + int status; + + ar = (struct ar6_softc *)arg; + A_ASSERT(ar != NULL); + A_ASSERT(!timer_pending(&aptcTimer)); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* Get the number of bytes transferred */ + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; + + /* Calculate and decide based on throughput thresholds */ + throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */ + if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) { + /* Enable Sleep and delete the timer */ + A_ASSERT(ar->arWmiReady == true); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + status = wmi_powermode_cmd(ar->arWmi, REC_POWER); + AR6000_SPIN_LOCK(&ar->arLock, 0); + A_ASSERT(status == 0); + aptcTR.timerScheduled = false; + } else { + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); +} +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +static void +ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num) +{ + void * osbuf; + + while(num) { + if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) { + A_NETBUF_ENQUEUE(q, osbuf); + } else { + break; + } + num--; + } + + if(num) { + A_PRINTF("%s(), allocation of netbuf failed", __func__); + } +} + +static struct bin_attribute bmi_attr = { + .attr = {.name = "bmi", .mode = 0600}, + .read = ar6000_sysfs_bmi_read, + .write = ar6000_sysfs_bmi_write, +}; + +static ssize_t +ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + int index; + struct ar6_softc *ar; + struct hif_device_os_device_info *osDevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count)); + for (index=0; index < MAX_AR6000; index++) { + ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); + osDevInfo = &ar->osDevInfo; + if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { + break; + } + } + + if (index == MAX_AR6000) return 0; + + if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) { + return 0; + } + + return count; +} + +static ssize_t +ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + int index; + struct ar6_softc *ar; + struct hif_device_os_device_info *osDevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count)); + for (index=0; index < MAX_AR6000; index++) { + ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); + osDevInfo = &ar->osDevInfo; + if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { + break; + } + } + + if (index == MAX_AR6000) return 0; + + if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) { + return 0; + } + + return count; +} + +static int +ar6000_sysfs_bmi_init(struct ar6_softc *ar) +{ + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n")); + A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info)); + + /* Get the underlying OS device */ + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_GET_OS_DEVICE, + &ar->osDevInfo, + sizeof(struct hif_device_os_device_info)); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n")); + return A_ERROR; + } + + /* Create a bmi entry in the sysfs filesystem */ + if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr)) < 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in sysfs filesystem\n")); + return A_ERROR; + } + + return 0; +} + +static void +ar6000_sysfs_bmi_deinit(struct ar6_softc *ar) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n")); + + sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr); +} + +#define bmifn(fn) do { \ + if ((fn) < 0) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \ + return A_ERROR; \ + } \ +} while(0) + +#ifdef SOFTMAC_FILE_USED +#define AR6002_MAC_ADDRESS_OFFSET 0x0A +#define AR6003_MAC_ADDRESS_OFFSET 0x16 +static +void calculate_crc(u32 TargetType, u8 *eeprom_data) +{ + u16 *ptr_crc; + u16 *ptr16_eeprom; + u16 checksum; + u32 i; + u32 eeprom_size; + + if (TargetType == TARGET_TYPE_AR6001) + { + eeprom_size = 512; + ptr_crc = (u16 *)eeprom_data; + } + else if (TargetType == TARGET_TYPE_AR6003) + { + eeprom_size = 1024; + ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); + } + else + { + eeprom_size = 768; + ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); + } + + + // Clear the crc + *ptr_crc = 0; + + // Recalculate new CRC + checksum = 0; + ptr16_eeprom = (u16 *)eeprom_data; + for (i = 0;i < eeprom_size; i += 2) + { + checksum = checksum ^ (*ptr16_eeprom); + ptr16_eeprom++; + } + checksum = 0xFFFF ^ checksum; + *ptr_crc = checksum; +} + +static void +ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size) +{ + const char *source = "random generated"; + const struct firmware *softmac_entry; + u8 *ptr_mac; + switch (ar->arTargetType) { + case TARGET_TYPE_AR6002: + ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET); + break; + case TARGET_TYPE_AR6003: + ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n")); + return; + } + printk(KERN_DEBUG "MAC from EEPROM %pM\n", ptr_mac); + + /* create a random MAC in case we cannot read file from system */ + ptr_mac[0] = 0; + ptr_mac[1] = 0x03; + ptr_mac[2] = 0x7F; + ptr_mac[3] = random32() & 0xff; + ptr_mac[4] = random32() & 0xff; + ptr_mac[5] = random32() & 0xff; + if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0) + { + char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1); + if (macbuf) { + unsigned int softmac[6]; + memcpy(macbuf, softmac_entry->data, softmac_entry->size); + macbuf[softmac_entry->size] = '\0'; + if (sscanf(macbuf, "%02x:%02x:%02x:%02x:%02x:%02x", + &softmac[0], &softmac[1], &softmac[2], + &softmac[3], &softmac[4], &softmac[5])==6) { + int i; + for (i=0; i<6; ++i) { + ptr_mac[i] = softmac[i] & 0xff; + } + source = "softmac file"; + } + kfree(macbuf); + } + A_RELEASE_FIRMWARE(softmac_entry); + } + printk(KERN_DEBUG "MAC from %s %pM\n", source, ptr_mac); + calculate_crc(ar->arTargetType, eeprom_data); +} +#endif /* SOFTMAC_FILE_USED */ + +static int +ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed) +{ + int status; + const char *filename; + const struct firmware *fw_entry; + u32 fw_entry_size; + u8 **buf; + size_t *buf_len; + + switch (file) { + case AR6K_OTP_FILE: + buf = &ar->fw_otp; + buf_len = &ar->fw_otp_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_OTP_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_OTP_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_OTP_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + case AR6K_FIRMWARE_FILE: + buf = &ar->fw; + buf_len = &ar->fw_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + + if (eppingtest) { + bypasswmi = true; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_EPPING_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_EPPING_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_EPPING_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("eppingtest : unsupported firmware revision: %d\n", + ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if(testmode) { + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_TCMD_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_TCMD_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_TCMD_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } +#endif +#ifdef HTC_RAW_INTERFACE + if (!eppingtest && bypasswmi) { + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_ART_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_ART_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } +#endif + break; + + case AR6K_PATCH_FILE: + buf = &ar->fw_patch; + buf_len = &ar->fw_patch_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_PATCH_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_PATCH_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_PATCH_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + case AR6K_BOARD_DATA_FILE: + buf = &ar->fw_data; + buf_len = &ar->fw_data_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_BOARD_DATA_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_BOARD_DATA_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_BOARD_DATA_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file)); + return A_ERROR; + } + + if (*buf == NULL) { + if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename)); + return A_ENOENT; + } + + *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); + *buf_len = fw_entry->size; + A_RELEASE_FIRMWARE(fw_entry); + } + +#ifdef SOFTMAC_FILE_USED + if (file==AR6K_BOARD_DATA_FILE && *buf_len) { + ar6000_softmac_update(ar, *buf, *buf_len); + } +#endif + + + fw_entry_size = *buf_len; + + /* Load extended board data for AR6003 */ + if ((file==AR6K_BOARD_DATA_FILE) && *buf) { + u32 board_ext_address; + u32 board_ext_data_size; + u32 board_data_size; + + board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0)); + + board_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_DATA_SZ : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0)); + + /* Determine where in Target RAM to write Board Data */ + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address)); + + /* check whether the target has allocated memory for extended board data and file contains extended board data */ + if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) { + u32 param; + + status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); + return A_ERROR; + } + + /* Record the fact that extended board Data IS initialized */ + param = (board_ext_data_size << 16) | 1; + bmifn(BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_config), + (unsigned char *)¶m, 4)); + } + fw_entry_size = board_data_size; + } + + if (compressed) { + status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size); + } else { + status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); + return A_ERROR; + } + + return 0; +} + +int +ar6000_update_bdaddr(struct ar6_softc *ar) +{ + + if (setupbtdev != 0) { + u32 address; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n")); + return A_ERROR; + } + + if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ar->bdaddr[0], + ar->bdaddr[1], ar->bdaddr[2], ar->bdaddr[3], + ar->bdaddr[4], ar->bdaddr[5])); + } + +return 0; +} + +int +ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n")); + + if (mode == WLAN_INIT_MODE_UDEV) { + char version[16]; + const struct firmware *fw_entry; + + /* Get config using udev through a script in user space */ + sprintf(version, "%2.2x", ar->arVersion.target_ver); + if ((A_REQUEST_FIRMWARE(&fw_entry, version, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get configuration for target version: %s\n", version)); + return A_ERROR; + } + + A_RELEASE_FIRMWARE(fw_entry); + } else { + /* The config is contained within the driver itself */ + int status; + u32 param, options, sleep, address; + + /* Temporarily disable system sleep */ + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + options = param; + param |= AR6K_OPTION_SLEEP_DISABLE; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + sleep = param; + param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", options, sleep)); + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Program analog PLL register */ + bmifn(BMIWriteSOCRegister(ar->arHifDevice, ANALOG_INTF_BASE_ADDRESS + 0x284, 0xF9104001)); + /* Run at 80/88MHz by default */ + param = CPU_CLOCK_STANDARD_SET(1); + } else { + /* Run at 40/44MHz by default */ + param = CPU_CLOCK_STANDARD_SET(0); + } + address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + param = 0; + if (ar->arTargetType == TARGET_TYPE_AR6002) { + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); + } + + /* LPO_CAL.ENABLE = 1 if no external clk is detected */ + if (param != 1) { + address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; + param = LPO_CAL_ENABLE_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } + + /* Venus2.0: Lower SDIO pad drive strength, + * temporary WAR to avoid SDIO CRC error */ + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6K: Temporary WAR to avoid SDIO CRC error\n")); + param = 0x20; + address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } + +#ifdef FORCE_INTERNAL_CLOCK + /* Ignore external clock, if any, and force use of internal clock */ + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* hi_ext_clk_detected = 0 */ + param = 0; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); + + /* CLOCK_CONTROL &= ~LF_CLK32 */ + address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + param &= (~CLOCK_CONTROL_LF_CLK32_SET(1)); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } +#endif /* FORCE_INTERNAL_CLOCK */ + + /* Transfer Board Data from Target EEPROM to Target RAM */ + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Determine where in Target RAM to write Board Data */ + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address)); + + /* Write EEPROM data to Target RAM */ + if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) { + return A_ERROR; + } + + /* Record the fact that Board Data IS initialized */ + param = 1; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)¶m, 4)); + + /* Transfer One time Programmable data */ + AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); + if (ar->arVersion.target_ver == AR6003_REV3_VERSION) + address = 0x1234; + status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true); + if (status == 0) { + /* Execute the OTP code */ + param = 0; + AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); + bmifn(BMIExecute(ar->arHifDevice, address, ¶m)); + } else if (status != A_ENOENT) { + return A_ERROR; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Programming of board data for chip %d not supported\n", ar->arTargetType)); + return A_ERROR; + } + + /* Download Target firmware */ + AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); + if (ar->arVersion.target_ver == AR6003_REV3_VERSION) + address = 0x1234; + if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) { + return A_ERROR; + } + + /* Set starting address for firmware */ + AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); + bmifn(BMISetAppStart(ar->arHifDevice, address)); + + if(ar->arTargetType == TARGET_TYPE_AR6003) { + AR6K_DATASET_PATCH_ADDRESS(address, ar->arVersion.target_ver); + if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, + address, false)) != 0) + return A_ERROR; + param = address; + bmifn(BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), + (unsigned char *)¶m, 4)); + } + + /* Restore system sleep */ + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep)); + + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + param = options | 0x20; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Configure GPIO AR6003 UART */ +#ifndef CONFIG_AR600x_DEBUG_UART_TX_PIN +#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 +#endif + param = CONFIG_AR600x_DEBUG_UART_TX_PIN; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)¶m, 4)); + +#if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23) + { + address = GPIO_BASE_ADDRESS + CLOCK_GPIO_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + param |= CLOCK_GPIO_BT_CLK_OUT_EN_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } +#endif + + /* Configure GPIO for BT Reset */ +#ifdef ATH6KL_CONFIG_GPIO_BT_RESET +#define CONFIG_AR600x_BT_RESET_PIN 0x16 + param = CONFIG_AR600x_BT_RESET_PIN; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)¶m, 4)); +#endif /* ATH6KL_CONFIG_GPIO_BT_RESET */ + + /* Configure UART flow control polarity */ +#ifndef CONFIG_ATH6KL_BT_UART_FC_POLARITY +#define CONFIG_ATH6KL_BT_UART_FC_POLARITY 0 +#endif + +#if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1) + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2); + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)¶m, 4)); + } +#endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */ + } + +#ifdef HTC_RAW_INTERFACE + if (!eppingtest && bypasswmi) { + /* Don't run BMIDone for ART mode and force resetok=0 */ + resetok = 0; + msleep(1000); + } +#endif /* HTC_RAW_INTERFACE */ + } + + return 0; +} + +int +ar6000_configure_target(struct ar6_softc *ar) +{ + u32 param; + if (enableuartprint) { + param = 1; + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n")); + } + + /* Tell target which HTC version it is used*/ + param = HTC_PROTOCOL_VERSION; + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n")); + return A_ERROR; + } + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if(testmode) { + ar->arTargetMode = AR6000_TCMD_MODE; + }else { + ar->arTargetMode = AR6000_WLAN_MODE; + } +#endif + if (enabletimerwar) { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n")); + return A_ERROR; + } + + param |= HI_OPTION_TIMER_WAR; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n")); + } + + /* set the firmware mode to STA/IBSS/AP */ + { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n")); + return A_ERROR; + } + + param |= (num_device << HI_OPTION_NUM_DEV_SHIFT); + param |= (fwmode << HI_OPTION_FW_MODE_SHIFT); + param |= (mac_addr_method << HI_OPTION_MAC_ADDR_METHOD_SHIFT); + param |= (firmware_bridge << HI_OPTION_FW_BRIDGE_SHIFT); + + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); + } + +#ifdef ATH6KL_DISABLE_TARGET_DBGLOGS + { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n")); + return A_ERROR; + } + + param |= HI_OPTION_DISABLE_DBGLOG; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); + } +#endif /* ATH6KL_DISABLE_TARGET_DBGLOGS */ + + /* + * Hardcode the address use for the extended board data + * Ideally this should be pre-allocate by the OS at boot time + * But since it is a new feature and board data is loaded + * at init time, we have to workaround this from host. + * It is difficult to patch the firmware boot code, + * but possible in theory. + */ + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + u32 ramReservedSz; + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; + ramReservedSz = AR6003_REV2_RAM_RESERVE_SIZE; + } else { + param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; + ramReservedSz = AR6003_REV3_RAM_RESERVE_SIZE; + } + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), + (u8 *)¶m, 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIWriteMemory for " + "hi_board_ext_data failed\n")); + return A_ERROR; + } + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_end_RAM_reserve_sz), + (u8 *)&ramReservedSz, 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR , + ("BMIWriteMemory for " + "hi_end_RAM_reserve_sz failed\n")); + return A_ERROR; + } + } + + /* since BMIInit is called in the driver layer, we have to set the block + * size here for the target */ + + if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType, + mbox_yield_limit, 0)) { + /* use default number of control buffers */ + return A_ERROR; + } + + if (setupbtdev != 0) { + if (ar6000_set_hci_bridge_flags(ar->arHifDevice, + ar->arTargetType, + setupbtdev)) { + return A_ERROR; + } + } + return 0; +} + +static void +init_netdev(struct net_device *dev, char *name) +{ + dev->netdev_ops = &ar6000_netdev_ops; + dev->watchdog_timeo = AR6000_TX_TIMEOUT; + + /* + * We need the OS to provide us with more headroom in order to + * perform dix to 802.3, WMI header encap, and the HTC header + */ + if (processDot11Hdr) { + dev->hard_header_len = sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; + } else { + dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) + + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; + } + + if (name[0]) + { + strcpy(dev->name, name); + } + +#ifdef CONFIG_CHECKSUM_OFFLOAD + if(csumOffload){ + dev->features |= NETIF_F_IP_CSUM; /*advertise kernel capability to do TCP/UDP CSUM offload for IPV4*/ + } +#endif + + return; +} + +static int __ath6kl_init_netdev(struct net_device *dev) +{ + int r; + + rtnl_lock(); + r = ar6000_init(dev); + rtnl_unlock(); + + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n")); + return r; + } + + return 0; +} + +#ifdef HTC_RAW_INTERFACE +static int ath6kl_init_netdev_wmi(struct net_device *dev) +{ + if (!eppingtest && bypasswmi) + return 0; + + return __ath6kl_init_netdev(dev); +} +#else +static int ath6kl_init_netdev_wmi(struct net_device *dev) +{ + return __ath6kl_init_netdev(dev); +} +#endif + +static int ath6kl_init_netdev(struct ar6_softc *ar) +{ + int r; + + r = ar6000_sysfs_bmi_get_config(ar, wlaninitmode); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("ar6000_avail: " + "ar6000_sysfs_bmi_get_config failed\n")); + return r; + } + + return ath6kl_init_netdev_wmi(ar->arNetDev); +} + +/* + * HTC Event handlers + */ +static int +ar6000_avail_ev(void *context, void *hif_handle) +{ + int i; + struct net_device *dev; + void *ar_netif; + struct ar6_softc *ar; + int device_index = 0; + struct htc_init_info htcInfo; + struct wireless_dev *wdev; + int r = 0; + struct hif_device_os_device_info osDevInfo; + + memset(&osDevInfo, 0, sizeof(osDevInfo)); + if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE, + &osDevInfo, sizeof(osDevInfo))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__)); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n")); + + for (i=0; i < MAX_AR6000; i++) { + if (ar6000_devices[i] == NULL) { + break; + } + } + + if (i == MAX_AR6000) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: max devices reached\n")); + return A_ERROR; + } + + /* Save this. It gives a bit better readability especially since */ + /* we use another local "i" variable below. */ + device_index = i; + + wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice); + if (IS_ERR(wdev)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__)); + return A_ERROR; + } + ar_netif = wdev_priv(wdev); + + if (ar_netif == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Can't allocate ar6k priv memory\n", __func__)); + return A_ERROR; + } + + A_MEMZERO(ar_netif, sizeof(struct ar6_softc)); + ar = (struct ar6_softc *)ar_netif; + + ar->wdev = wdev; + wdev->iftype = NL80211_IFTYPE_STATION; + + dev = alloc_netdev_mq(0, "wlan%d", ether_setup, 1); + if (!dev) { + printk(KERN_CRIT "AR6K: no memory for network device instance\n"); + ar6k_cfg80211_deinit(ar); + return A_ERROR; + } + + dev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); + wdev->netdev = dev; + ar->arNetworkType = INFRA_NETWORK; + ar->smeState = SME_DISCONNECTED; + ar->arAutoAuthStage = AUTH_IDLE; + + init_netdev(dev, ifname); + + + ar->arNetDev = dev; + ar->arHifDevice = hif_handle; + ar->arWlanState = WLAN_ENABLED; + ar->arDeviceIndex = device_index; + + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + ar->arWlanOff = false; /* We are in ON state */ +#ifdef CONFIG_PM + ar->arWowState = WLAN_WOW_STATE_NONE; + ar->arBTOff = true; /* BT chip assumed to be OFF */ + ar->arBTSharing = WLAN_CONFIG_BT_SHARING; + ar->arWlanOffConfig = WLAN_CONFIG_WLAN_OFF; + ar->arSuspendConfig = WLAN_CONFIG_PM_SUSPEND; + ar->arWow2Config = WLAN_CONFIG_PM_WOW2; +#endif /* CONFIG_PM */ + + A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev); + ar->arHBChallengeResp.seqNum = 0; + ar->arHBChallengeResp.outstanding = false; + ar->arHBChallengeResp.missCnt = 0; + ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT; + ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT; + + ar6000_init_control_info(ar); + init_waitqueue_head(&arEvent); + sema_init(&ar->arSem, 1); + ar->bIsDestroyProgress = false; + + INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue); + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + A_INIT_TIMER(&ar->disconnect_timer, disconnect_timer_handler, dev); + + BMIInit(); + + ar6000_sysfs_bmi_init(ar); + + { + struct bmi_target_info targ_info; + + r = BMIGetTargetInfo(ar->arHifDevice, &targ_info); + if (r) + goto avail_ev_failed; + + ar->arVersion.target_ver = targ_info.target_ver; + ar->arTargetType = targ_info.target_type; + wdev->wiphy->hw_version = targ_info.target_ver; + } + + r = ar6000_configure_target(ar); + if (r) + goto avail_ev_failed; + + A_MEMZERO(&htcInfo,sizeof(htcInfo)); + htcInfo.pContext = ar; + htcInfo.TargetFailure = ar6000_target_failure; + + ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo); + + if (!ar->arHtcTarget) { + r = -ENOMEM; + goto avail_ev_failed; + } + + spin_lock_init(&ar->arLock); + +#ifdef WAPI_ENABLE + ar->arWapiEnable = 0; +#endif + + + if(csumOffload){ + /*if external frame work is also needed, change and use an extended rxMetaVerion*/ + ar->rxMetaVersion=WMI_META_VERSION_2; + } + + ar->aggr_cntxt = aggr_init(ar6000_alloc_netbufs); + if (!ar->aggr_cntxt) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize aggr.\n", __func__)); + r = -ENOMEM; + goto avail_ev_failed; + } + + aggr_register_rx_dispatcher(ar->aggr_cntxt, (void *)dev, ar6000_deliver_frames_to_nw_stack); + + HIFClaimDevice(ar->arHifDevice, ar); + + /* We only register the device in the global list if we succeed. */ + /* If the device is in the global list, it will be destroyed */ + /* when the module is unloaded. */ + ar6000_devices[device_index] = dev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BMI enabled: %d\n", wlaninitmode)); + if ((wlaninitmode == WLAN_INIT_MODE_UDEV) || + (wlaninitmode == WLAN_INIT_MODE_DRV)) { + r = ath6kl_init_netdev(ar); + if (r) + goto avail_ev_failed; + } + + /* This runs the init function if registered */ + r = register_netdev(dev); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: register_netdev failed\n")); + ar6000_destroy(dev, 0); + return r; + } + + is_netdev_registered = 1; + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT + arApNetDev = NULL; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_avail: name=%s hifdevice=0x%lx, dev=0x%lx (%d), ar=0x%lx\n", + dev->name, (unsigned long)ar->arHifDevice, (unsigned long)dev, device_index, + (unsigned long)ar)); + +avail_ev_failed : + if (r) + ar6000_sysfs_bmi_deinit(ar); + + return r; +} + +static void ar6000_target_failure(void *Instance, int Status) +{ + struct ar6_softc *ar = (struct ar6_softc *)Instance; + WMI_TARGET_ERROR_REPORT_EVENT errEvent; + static bool sip = false; + + if (Status != 0) { + + printk(KERN_ERR "ar6000_target_failure: target asserted \n"); + + if (timer_pending(&ar->arHBChallengeResp.timer)) { + A_UNTIMEOUT(&ar->arHBChallengeResp.timer); + } + + /* try dumping target assertion information (if any) */ + ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType); + + /* + * Fetch the logs from the target via the diagnostic + * window. + */ + ar6000_dbglog_get_debug_logs(ar); + + /* Report the error only once */ + if (!sip) { + sip = true; + errEvent.errorVal = WMI_TARGET_COM_ERR | + WMI_TARGET_FATAL_ERR; + } + } +} + +static int +ar6000_unavail_ev(void *context, void *hif_handle) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + /* NULL out it's entry in the global list */ + ar6000_devices[ar->arDeviceIndex] = NULL; + ar6000_destroy(ar->arNetDev, 1); + + return 0; +} + +void +ar6000_restart_endpoint(struct net_device *dev) +{ + int status = 0; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + BMIInit(); + do { + if ( (status=ar6000_configure_target(ar))!= 0) + break; + if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n")); + break; + } + rtnl_lock(); + status = (ar6000_init(dev)==0) ? 0 : A_ERROR; + rtnl_unlock(); + + if (status) { + break; + } + if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) { + ar6000_connect_to_ap(ar); + } + } while (0); + + if (status== 0) { + return; + } + + ar6000_devices[ar->arDeviceIndex] = NULL; + ar6000_destroy(ar->arNetDev, 1); +} + +void +ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + /* Stop the transmit queues */ + netif_stop_queue(dev); + + /* Disable the target and the interrupts associated with it */ + if (ar->arWmiReady == true) + { + if (!bypasswmi) + { + bool disconnectIssued; + + disconnectIssued = (ar->arConnected) || (ar->arConnectPending); + ar6000_disconnect(ar); + if (!keepprofile) { + ar6000_init_profile_info(ar); + } + + A_UNTIMEOUT(&ar->disconnect_timer); + + if (getdbglogs) { + ar6000_dbglog_get_debug_logs(ar); + } + + ar->arWmiReady = false; + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + /* + * After wmi_shudown all WMI events will be dropped. + * We need to cleanup the buffers allocated in AP mode + * and give disconnect notification to stack, which usually + * happens in the disconnect_event. + * Simulate the disconnect_event by calling the function directly. + * Sometimes disconnect_event will be received when the debug logs + * are collected. + */ + if (disconnectIssued) { + if(ar->arNetworkType & AP_NETWORK) { + ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0); + } else { + ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0); + } + } + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI stopped\n", __func__)); + } + else + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI not ready 0x%lx 0x%lx\n", + __func__, (unsigned long) ar, (unsigned long) ar->arWmi)); + + /* Shut down WMI if we have started it */ + if(ar->arWmiEnabled == true) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__)); + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + } + } + + if (ar->arHtcTarget != NULL) { +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + if (NULL != ar6kHciTransCallbacks.cleanupTransport) { + ar6kHciTransCallbacks.cleanupTransport(NULL); + } +#else + // FIXME: workaround to reset BT's UART baud rate to default + if (NULL != ar->exitCallback) { + struct ar3k_config_info ar3kconfig; + int status; + + A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); + ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig); + status = ar->exitCallback(&ar3kconfig); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n")); + } + } + // END workaround + if (setuphci) + ar6000_cleanup_hci(ar); +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Shutting down HTC .... \n")); + /* stop HTC */ + HTCStop(ar->arHtcTarget); + } + + if (resetok) { + /* try to reset the device if we can + * The driver may have been configure NOT to reset the target during + * a debug session */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n")); + if (ar->arHifDevice != NULL) { + bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false; + ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n")); + } + /* Done with cookies */ + ar6000_cookie_cleanup(ar); + + /* cleanup any allocated AMSDU buffers */ + ar6000_cleanup_amsdu_rxbufs(ar); +} +/* + * We need to differentiate between the surprise and planned removal of the + * device because of the following consideration: + * - In case of surprise removal, the hcd already frees up the pending + * for the device and hence there is no need to unregister the function + * driver inorder to get these requests. For planned removal, the function + * driver has to explicitly unregister itself to have the hcd return all the + * pending requests before the data structures for the devices are freed up. + * Note that as per the current implementation, the function driver will + * end up releasing all the devices since there is no API to selectively + * release a particular device. + * - Certain commands issued to the target can be skipped for surprise + * removal since they will anyway not go through. + */ +void +ar6000_destroy(struct net_device *dev, unsigned int unregister) +{ + struct ar6_softc *ar; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n")); + + if((dev == NULL) || ((ar = ar6k_priv(dev)) == NULL)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): Failed to get device structure.\n", __func__)); + return; + } + + ar->bIsDestroyProgress = true; + + if (down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__)); + return; + } + + if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { + /* only stop endpoint if we are not stop it in suspend_ev */ + ar6000_stop_endpoint(dev, false, true); + } + + ar->arWlanState = WLAN_DISABLED; + if (ar->arHtcTarget != NULL) { + /* destroy HTC */ + HTCDestroy(ar->arHtcTarget); + } + if (ar->arHifDevice != NULL) { + /*release the device so we do not get called back on remove incase we + * we're explicity destroyed by module unload */ + HIFReleaseDevice(ar->arHifDevice); + HIFShutDownDevice(ar->arHifDevice); + } + aggr_module_destroy(ar->aggr_cntxt); + + /* Done with cookies */ + ar6000_cookie_cleanup(ar); + + /* cleanup any allocated AMSDU buffers */ + ar6000_cleanup_amsdu_rxbufs(ar); + + ar6000_sysfs_bmi_deinit(ar); + + /* Cleanup BMI */ + BMICleanup(); + + /* Clear the tx counters */ + memset(tx_attempt, 0, sizeof(tx_attempt)); + memset(tx_post, 0, sizeof(tx_post)); + memset(tx_complete, 0, sizeof(tx_complete)); + +#ifdef HTC_RAW_INTERFACE + if (ar->arRawHtc) { + kfree(ar->arRawHtc); + ar->arRawHtc = NULL; + } +#endif + /* Free up the device data structure */ + if (unregister && is_netdev_registered) { + unregister_netdev(dev); + is_netdev_registered = 0; + } + free_netdev(dev); + + ar6k_cfg80211_deinit(ar); + +#ifdef CONFIG_AP_VIRTUL_ADAPTER_SUPPORT + ar6000_remove_ap_interface(); +#endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + + kfree(ar->fw_otp); + kfree(ar->fw); + kfree(ar->fw_patch); + kfree(ar->fw_data); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n")); +} + +static void disconnect_timer_handler(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + A_UNTIMEOUT(&ar->disconnect_timer); + + ar6000_init_profile_info(ar); + ar6000_disconnect(ar); +} + +static void ar6000_detect_error(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + WMI_TARGET_ERROR_REPORT_EVENT errEvent; + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (ar->arHBChallengeResp.outstanding) { + ar->arHBChallengeResp.missCnt++; + } else { + ar->arHBChallengeResp.missCnt = 0; + } + + if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) { + /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */ + ar->arHBChallengeResp.missCnt = 0; + ar->arHBChallengeResp.seqNum = 0; + errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + return; + } + + /* Generate the sequence number for the next challenge */ + ar->arHBChallengeResp.seqNum++; + ar->arHBChallengeResp.outstanding = true; + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + /* Send the challenge on the control channel */ + if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n")); + } + + + /* Reschedule the timer for the next challenge */ + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0); +} + +void ar6000_init_profile_info(struct ar6_softc *ar) +{ + ar->arSsidLen = 0; + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + + switch(fwmode) { + case HI_OPTION_FW_MODE_IBSS: + ar->arNetworkType = ar->arNextMode = ADHOC_NETWORK; + break; + case HI_OPTION_FW_MODE_BSS_STA: + ar->arNetworkType = ar->arNextMode = INFRA_NETWORK; + break; + case HI_OPTION_FW_MODE_AP: + ar->arNetworkType = ar->arNextMode = AP_NETWORK; + break; + } + + ar->arDot11AuthMode = OPEN_AUTH; + ar->arAuthMode = NONE_AUTH; + ar->arPairwiseCrypto = NONE_CRYPT; + ar->arPairwiseCryptoLen = 0; + ar->arGroupCrypto = NONE_CRYPT; + ar->arGroupCryptoLen = 0; + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); + ar->arBssChannel = 0; +} + +static void +ar6000_init_control_info(struct ar6_softc *ar) +{ + ar->arWmiEnabled = false; + ar6000_init_profile_info(ar); + ar->arDefTxKeyIndex = 0; + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); + ar->arChannelHint = 0; + ar->arListenIntervalT = A_DEFAULT_LISTEN_INTERVAL; + ar->arListenIntervalB = 0; + ar->arVersion.host_ver = AR6K_SW_VERSION; + ar->arRssi = 0; + ar->arTxPwr = 0; + ar->arTxPwrSet = false; + ar->arSkipScan = 0; + ar->arBeaconInterval = 0; + ar->arBitRate = 0; + ar->arMaxRetries = 0; + ar->arWmmEnabled = true; + ar->intra_bss = 1; + ar->scan_triggered = 0; + A_MEMZERO(&ar->scParams, sizeof(ar->scParams)); + ar->scParams.shortScanRatio = WMI_SHORTSCANRATIO_DEFAULT; + ar->scParams.scanCtrlFlags = DEFAULT_SCAN_CTRL_FLAGS; + + /* Initialize the AP mode state info */ + { + u8 ctr; + A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t)); + + /* init the Mutexes */ + A_MUTEX_INIT(&ar->mcastpsqLock); + + /* Init the PS queues */ + for (ctr=0; ctr < AP_MAX_NUM_STA ; ctr++) { + A_MUTEX_INIT(&ar->sta_list[ctr].psqLock); + A_NETBUF_QUEUE_INIT(&ar->sta_list[ctr].psq); + } + + ar->ap_profile_flag = 0; + A_NETBUF_QUEUE_INIT(&ar->mcastpsq); + + memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); + ar->ap_wmode = DEF_AP_WMODE_G; + ar->ap_dtim_period = DEF_AP_DTIM; + ar->ap_beacon_interval = DEF_BEACON_INTERVAL; + } +} + +static int +ar6000_open(struct net_device *dev) +{ + unsigned long flags; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + spin_lock_irqsave(&ar->arLock, flags); + + if(ar->arWlanState == WLAN_DISABLED) { + ar->arWlanState = WLAN_ENABLED; + } + + if( ar->arConnected || bypasswmi) { + netif_carrier_on(dev); + /* Wake up the queues */ + netif_wake_queue(dev); + } + else + netif_carrier_off(dev); + + spin_unlock_irqrestore(&ar->arLock, flags); + return 0; +} + +static int +ar6000_close(struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + netif_stop_queue(dev); + + ar6000_disconnect(ar); + + if(ar->arWmiReady == true) { + if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, + 0, 0, 0, 0, 0, 0, 0, 0) != 0) { + return -EIO; + } + ar->arWlanState = WLAN_DISABLED; + } + ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED); + + return 0; +} + +/* connect to a service */ +static int ar6000_connectservice(struct ar6_softc *ar, + struct htc_service_connect_req *pConnect, + char *pDesc) +{ + int status; + struct htc_service_connect_resp response; + + do { + + A_MEMZERO(&response,sizeof(response)); + + status = HTCConnectService(ar->arHtcTarget, + pConnect, + &response); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n", + pDesc, status)); + break; + } + switch (pConnect->ServiceID) { + case WMI_CONTROL_SVC : + if (ar->arWmiEnabled) { + /* set control endpoint for WMI use */ + wmi_set_control_ep(ar->arWmi, response.Endpoint); + } + /* save EP for fast lookup */ + ar->arControlEp = response.Endpoint; + break; + case WMI_DATA_BE_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_BE, response.Endpoint); + break; + case WMI_DATA_BK_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_BK, response.Endpoint); + break; + case WMI_DATA_VI_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_VI, response.Endpoint); + break; + case WMI_DATA_VO_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_VO, response.Endpoint); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ServiceID not mapped %d\n", pConnect->ServiceID)); + status = A_EINVAL; + break; + } + + } while (false); + + return status; +} + +void ar6000_TxDataCleanup(struct ar6_softc *ar) +{ + /* flush all the data (non-control) streams + * we only flush packets that are tagged as data, we leave any control packets that + * were in the TX queues alone */ + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_BE), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_BK), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_VI), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_VO), + AR6K_DATA_PKT_TAG); +} + +HTC_ENDPOINT_ID +ar6000_ac2_endpoint_id ( void * devt, u8 ac) +{ + struct ar6_softc *ar = (struct ar6_softc *) devt; + return(arAc2EndpointID(ar, ac)); +} + +u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep ) +{ + struct ar6_softc *ar = (struct ar6_softc *) devt; + return(arEndpoint2Ac(ar, ep )); +} + +#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) +static int ath6kl_config_btcoex_params(struct ar6_softc *ar) +{ + int r; + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd; + WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd; + + /* Configure the type of BT collocated with WLAN */ + memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); + sbcb_cmd.btcoexCoLocatedBTdev = ATH6KL_BT_DEV; + + r = wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd); + + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to set collocated BT type\n")); + return r; + } + + /* Configure the type of BT collocated with WLAN */ + memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); + + sbfa_cmd.btcoexFeAntType = ATH6KL_BT_ANTENNA; + + r = wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to set fornt end antenna configuration\n")); + return r; + } + + return 0; +} +#else +static int ath6kl_config_btcoex_params(struct ar6_softc *ar) +{ + return 0; +} +#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ + +/* + * This function applies WLAN specific configuration defined in wlan_config.h + */ +int ar6000_target_config_wlan_params(struct ar6_softc *ar) +{ + int status = 0; + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if (ar->arTargetMode != AR6000_WLAN_MODE) { + return 0; + } +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + + /* + * configure the device for rx dot11 header rules 0,0 are the default values + * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required + * if checksum offload is needed. Set RxMetaVersion to 2 + */ + if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n")); + status = A_ERROR; + } + + status = ath6kl_config_btcoex_params(ar); + if (status) + return status; + +#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN + if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n")); + status = A_ERROR; + } +#endif + +#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP + if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n")); + status = A_ERROR; + } +#endif + + if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n")); + status = A_ERROR; + } + +#if WLAN_CONFIG_DISABLE_11N + { + WMI_SET_HT_CAP_CMD htCap; + + memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD)); + htCap.band = 0; + if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); + status = A_ERROR; + } + + htCap.band = 1; + if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); + status = A_ERROR; + } + } +#endif /* WLAN_CONFIG_DISABLE_11N */ + +#ifdef ATH6K_CONFIG_OTA_MODE + if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n")); + status = A_ERROR; + } +#endif + + if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n")); + status = A_ERROR; + } + +#if WLAN_CONFIG_DISABLE_TX_BURSTING + if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n")); + status = A_ERROR; + } +#endif + + return status; +} + +/* This function does one time initialization for the lifetime of the device */ +int ar6000_init(struct net_device *dev) +{ + struct ar6_softc *ar; + int status; + s32 timeleft; + s16 i; + int ret = 0; + + if((ar = ar6k_priv(dev)) == NULL) + { + return -EIO; + } + + if (wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) { + + ar6000_update_bdaddr(ar); + + if (enablerssicompensation) { + ar6000_copy_cust_data_from_target(ar->arHifDevice, ar->arTargetType); + read_rssi_compensation_param(ar); + for (i=-95; i<=0; i++) { + rssi_compensation_table[0-i] = rssi_compensation_calc(ar,i); + } + } + } + + dev_hold(dev); + rtnl_unlock(); + + /* Do we need to finish the BMI phase */ + if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) && + (BMIDone(ar->arHifDevice) != 0)) + { + ret = -EIO; + goto ar6000_init_done; + } + + if (!bypasswmi) + { +#if 0 /* TBDXXX */ + if (ar->arVersion.host_ver != ar->arVersion.target_ver) { + A_PRINTF("WARNING: Host version 0x%x does not match Target " + " version 0x%x!\n", + ar->arVersion.host_ver, ar->arVersion.target_ver); + } +#endif + + /* Indicate that WMI is enabled (although not ready yet) */ + ar->arWmiEnabled = true; + if ((ar->arWmi = wmi_init((void *) ar)) == NULL) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__)); + ret = -EIO; + goto ar6000_init_done; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Got WMI @ 0x%lx.\n", __func__, + (unsigned long) ar->arWmi)); + } + + do { + struct htc_service_connect_req connect; + + /* the reason we have to wait for the target here is that the driver layer + * has to init BMI in order to set the host block size, + */ + status = HTCWaitTarget(ar->arHtcTarget); + + if (status) { + break; + } + + A_MEMZERO(&connect,sizeof(connect)); + /* meta data is unused for now */ + connect.pMetaData = NULL; + connect.MetaDataLength = 0; + /* these fields are the same for all service endpoints */ + connect.EpCallbacks.pContext = ar; + connect.EpCallbacks.EpTxCompleteMultiple = ar6000_tx_complete; + connect.EpCallbacks.EpRecv = ar6000_rx; + connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill; + connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full; + /* set the max queue depth so that our ar6000_tx_queue_full handler gets called. + * Linux has the peculiarity of not providing flow control between the + * NIC and the network stack. There is no API to indicate that a TX packet + * was sent which could provide some back pressure to the network stack. + * Under linux you would have to wait till the network stack consumed all sk_buffs + * before any back-flow kicked in. Which isn't very friendly. + * So we have to manage this ourselves */ + connect.MaxSendQueueDepth = MAX_DEFAULT_SEND_QUEUE_DEPTH; + connect.EpCallbacks.RecvRefillWaterMark = AR6000_MAX_RX_BUFFERS / 4; /* set to 25 % */ + if (0 == connect.EpCallbacks.RecvRefillWaterMark) { + connect.EpCallbacks.RecvRefillWaterMark++; + } + /* connect to control service */ + connect.ServiceID = WMI_CONTROL_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI CONTROL"); + if (status) { + break; + } + + connect.LocalConnectionFlags |= HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING; + /* limit the HTC message size on the send path, although we can receive A-MSDU frames of + * 4K, we will only send ethernet-sized (802.3) frames on the send path. */ + connect.MaxSendMsgSize = WMI_MAX_TX_DATA_FRAME_LENGTH; + + /* to reduce the amount of committed memory for larger A_MSDU frames, use the recv-alloc threshold + * mechanism for larger packets */ + connect.EpCallbacks.RecvAllocThreshold = AR6000_BUFFER_SIZE; + connect.EpCallbacks.EpRecvAllocThresh = ar6000_alloc_amsdu_rxbuf; + + /* for the remaining data services set the connection flag to reduce dribbling, + * if configured to do so */ + if (reduce_credit_dribble) { + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE; + /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value + * of 0-3 */ + connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; + connect.ConnectionFlags |= + ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; + } + /* connect to best-effort service */ + connect.ServiceID = WMI_DATA_BE_SVC; + + status = ar6000_connectservice(ar, + &connect, + "WMI DATA BE"); + if (status) { + break; + } + + /* connect to back-ground + * map this to WMI LOW_PRI */ + connect.ServiceID = WMI_DATA_BK_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA BK"); + if (status) { + break; + } + + /* connect to Video service, map this to + * to HI PRI */ + connect.ServiceID = WMI_DATA_VI_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA VI"); + if (status) { + break; + } + + /* connect to VO service, this is currently not + * mapped to a WMI priority stream due to historical reasons. + * WMI originally defined 3 priorities over 3 mailboxes + * We can change this when WMI is reworked so that priorities are not + * dependent on mailboxes */ + connect.ServiceID = WMI_DATA_VO_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA VO"); + if (status) { + break; + } + + A_ASSERT(arAc2EndpointID(ar,WMM_AC_BE) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_BK) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_VI) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_VO) != 0); + + /* setup access class priority mappings */ + ar->arAcStreamPriMap[WMM_AC_BK] = 0; /* lowest */ + ar->arAcStreamPriMap[WMM_AC_BE] = 1; /* */ + ar->arAcStreamPriMap[WMM_AC_VI] = 2; /* */ + ar->arAcStreamPriMap[WMM_AC_VO] = 3; /* highest */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) { + struct hci_transport_misc_handles hciHandles; + + hciHandles.netDevice = ar->arNetDev; + hciHandles.hifDevice = ar->arHifDevice; + hciHandles.htcHandle = ar->arHtcTarget; + status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles)); + } +#else + if (setuphci) { + /* setup HCI */ + status = ar6000_setup_hci(ar); + } +#endif + + } while (false); + + if (status) { + ret = -EIO; + goto ar6000_init_done; + } + + if (regscanmode) { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_option_flag), + (u8 *)¶m, + 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIReadMemory forsetting " + "regscanmode failed\n")); + return A_ERROR; + } + + if (regscanmode == 1) + param |= HI_OPTION_SKIP_REG_SCAN; + else if (regscanmode == 2) + param |= HI_OPTION_INIT_REG_SCAN; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_option_flag), + (u8 *)¶m, + 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIWriteMemory forsetting " + "regscanmode failed\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Regulatory scan mode set\n")); + } + + /* + * give our connected endpoints some buffers + */ + + ar6000_rx_refill(ar, ar->arControlEp); + ar6000_rx_refill(ar, arAc2EndpointID(ar,WMM_AC_BE)); + + /* + * We will post the receive buffers only for SPE or endpoint ping testing so we are + * making it conditional on the 'bypasswmi' flag. + */ + if (bypasswmi) { + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_BK)); + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VI)); + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VO)); + } + + /* allocate some buffers that handle larger AMSDU frames */ + ar6000_refill_amsdu_rxbufs(ar,AR6000_MAX_AMSDU_RX_BUFFERS); + + /* setup credit distribution */ + ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo); + + /* Since cookies are used for HTC transports, they should be */ + /* initialized prior to enabling HTC. */ + ar6000_cookie_init(ar); + + /* start HTC */ + status = HTCStart(ar->arHtcTarget); + + if (status) { + if (ar->arWmiEnabled == true) { + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + } + ar6000_cookie_cleanup(ar); + ret = -EIO; + goto ar6000_init_done; + } + + if (!bypasswmi) { + /* Wait for Wmi event to be ready */ + timeleft = wait_event_interruptible_timeout(arEvent, + (ar->arWmiReady == true), wmitimeout * HZ); + + if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver)); +#ifndef ATH6K_SKIP_ABI_VERSION_CHECK + ret = -EIO; + goto ar6000_init_done; +#endif /* ATH6K_SKIP_ABI_VERSION_CHECK */ + } + + if(!timeleft || signal_pending(current)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI is not ready or wait was interrupted\n")); + ret = -EIO; + goto ar6000_init_done; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__)); + + /* Communicate the wmi protocol verision to the target */ + if ((ar6000_set_host_app_area(ar)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n")); + } + ar6000_target_config_wlan_params(ar); + } + + ar->arNumDataEndPts = 1; + + if (bypasswmi) { + /* for tests like endpoint ping, the MAC address needs to be non-zero otherwise + * the data path through a raw socket is disabled */ + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x01; + dev->dev_addr[2] = 0x02; + dev->dev_addr[3] = 0xAA; + dev->dev_addr[4] = 0xBB; + dev->dev_addr[5] = 0xCC; + } + +ar6000_init_done: + rtnl_lock(); + dev_put(dev); + + return ret; +} + + +void +ar6000_bitrate_rx(void *devt, s32 rateKbps) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arBitRate = rateKbps; + wake_up(&arEvent); +} + +void +ar6000_ratemask_rx(void *devt, u32 ratemask) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arRateMask = ratemask; + wake_up(&arEvent); +} + +void +ar6000_txPwr_rx(void *devt, u8 txPwr) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arTxPwr = txPwr; + wake_up(&arEvent); +} + + +void +ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + memcpy(ar->arChannelList, chanList, numChan * sizeof (u16)); + ar->arNumChannels = numChan; + + wake_up(&arEvent); +} + +u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + u8 *datap; + ATH_MAC_HDR *macHdr; + u32 i, eptMap; + + (*mapNo) = 0; + datap = A_NETBUF_DATA(skb); + macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR)); + if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) { + return ENDPOINT_2; + } + + eptMap = -1; + for (i = 0; i < ar->arNodeNum; i ++) { + if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) { + (*mapNo) = i + 1; + ar->arNodeMap[i].txPending ++; + return ar->arNodeMap[i].epId; + } + + if ((eptMap == -1) && !ar->arNodeMap[i].txPending) { + eptMap = i; + } + } + + if (eptMap == -1) { + eptMap = ar->arNodeNum; + ar->arNodeNum ++; + A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM); + } + + memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN); + + for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) { + if (!ar->arTxPending[i]) { + ar->arNodeMap[eptMap].epId = i; + break; + } + // No free endpoint is available, start redistribution on the inuse endpoints. + if (i == ENDPOINT_5) { + ar->arNodeMap[eptMap].epId = ar->arNexEpId; + ar->arNexEpId ++; + if (ar->arNexEpId > ENDPOINT_5) { + ar->arNexEpId = ENDPOINT_2; + } + } + } + + (*mapNo) = eptMap + 1; + ar->arNodeMap[eptMap].txPending ++; + + return ar->arNodeMap[eptMap].epId; +} + +#ifdef DEBUG +static void ar6000_dump_skb(struct sk_buff *skb) +{ + u_char *ch; + for (ch = A_NETBUF_DATA(skb); + (unsigned long)ch < ((unsigned long)A_NETBUF_DATA(skb) + + A_NETBUF_LEN(skb)); ch++) + { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("%2.2x ", *ch)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("\n")); +} +#endif + +#ifdef HTC_TEST_SEND_PKTS +static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb); +#endif + +static int +ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) +{ +#define AC_NOT_MAPPED 99 + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + u8 ac = AC_NOT_MAPPED; + HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; + u32 mapNo = 0; + int len; + struct ar_cookie *cookie; + bool checkAdHocPsMapping = false,bMoreData = false; + HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; + u8 dot11Hdr = processDot11Hdr; +#ifdef CONFIG_PM + if (ar->arWowState != WLAN_WOW_STATE_NONE) { + A_NETBUF_FREE(skb); + return 0; + } +#endif /* CONFIG_PM */ + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_data_tx start - skb=0x%lx, data=0x%lx, len=0x%x\n", + (unsigned long)skb, (unsigned long)A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb))); + + /* If target is not associated */ + if( (!ar->arConnected && !bypasswmi) +#ifdef CONFIG_HOST_TCMD_SUPPORT + /* TCMD doesn't support any data, free the buf and return */ + || (ar->arTargetMode == AR6000_TCMD_MODE) +#endif + ) { + A_NETBUF_FREE(skb); + return 0; + } + + do { + + if (ar->arWmiReady == false && bypasswmi == 0) { + break; + } + +#ifdef BLOCK_TX_PATH_FLAG + if (blocktx) { + break; + } +#endif /* BLOCK_TX_PATH_FLAG */ + + /* AP mode Power save processing */ + /* If the dst STA is in sleep state, queue the pkt in its PS queue */ + + if (ar->arNetworkType == AP_NETWORK) { + ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); + sta_t *conn = NULL; + + /* If the dstMac is a Multicast address & atleast one of the + * associated STA is in PS mode, then queue the pkt to the + * mcastq + */ + if (IEEE80211_IS_MULTICAST(datap->dstMac)) { + u8 ctr=0; + bool qMcast=false; + + + for (ctr=0; ctrsta_list[ctr]))) { + qMcast = true; + } + } + if(qMcast) { + + /* If this transmit is not because of a Dtim Expiry q it */ + if (ar->DTIMExpired == false) { + bool isMcastqEmpty = false; + + A_MUTEX_LOCK(&ar->mcastpsqLock); + isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); + A_NETBUF_ENQUEUE(&ar->mcastpsq, skb); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* If this is the first Mcast pkt getting queued + * indicate to the target to set the BitmapControl LSB + * of the TIM IE. + */ + if (isMcastqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 1); + } + return 0; + } else { + /* This transmit is because of Dtim expiry. Determine if + * MoreData bit has to be set. + */ + A_MUTEX_LOCK(&ar->mcastpsqLock); + if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + bMoreData = true; + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + } + } + } else { + conn = ieee80211_find_conn(ar, datap->dstMac); + if (conn) { + if (STA_IS_PWR_SLEEP(conn)) { + /* If this transmit is not because of a PsPoll q it*/ + if (!STA_IS_PS_POLLED(conn)) { + bool isPsqEmpty = false; + /* Queue the frames if the STA is sleeping */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_NETBUF_ENQUEUE(&conn->psq, skb); + A_MUTEX_UNLOCK(&conn->psqLock); + + /* If this is the first pkt getting queued + * for this STA, update the PVB for this STA + */ + if (isPsqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 1); + } + + return 0; + } else { + /* This tx is because of a PsPoll. Determine if + * MoreData bit has to be set + */ + A_MUTEX_LOCK(&conn->psqLock); + if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { + bMoreData = true; + } + A_MUTEX_UNLOCK(&conn->psqLock); + } + } + } else { + + /* non existent STA. drop the frame */ + A_NETBUF_FREE(skb); + return 0; + } + } + } + + if (ar->arWmiEnabled) { + u8 csumStart=0; + u8 csumDest=0; + u8 csum=skb->ip_summed; + if(csumOffload && (csum==CHECKSUM_PARTIAL)){ + csumStart = (skb->head + skb->csum_start - skb_network_header(skb) + + sizeof(ATH_LLC_SNAP_HDR)); + csumDest=skb->csum_offset+csumStart; + } + if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len - LINUX_HACK_FUDGE_FACTOR) { + struct sk_buff *newbuf; + + /* + * We really should have gotten enough headroom but sometimes + * we still get packets with not enough headroom. Copy the packet. + */ + len = A_NETBUF_LEN(skb); + newbuf = A_NETBUF_ALLOC(len); + if (newbuf == NULL) { + break; + } + A_NETBUF_PUT(newbuf, len); + memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len); + A_NETBUF_FREE(skb); + skb = newbuf; + /* fall through and assemble header */ + } + + if (dot11Hdr) { + if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n")); + break; + } + } else { + if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n")); + break; + } + } + if(csumOffload && (csum ==CHECKSUM_PARTIAL)){ + WMI_TX_META_V2 metaV2; + metaV2.csumStart =csumStart; + metaV2.csumDest = csumDest; + metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/ + if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr, + WMI_META_VERSION_2,&metaV2) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); + break; + } + + } + else + { + if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); + break; + } + } + + + if ((ar->arNetworkType == ADHOC_NETWORK) && + ar->arIbssPsEnable && ar->arConnected) { + /* flag to check adhoc mapping once we take the lock below: */ + checkAdHocPsMapping = true; + + } else { + /* get the stream mapping */ + ac = wmi_implicit_create_pstream(ar->arWmi, skb, 0, ar->arWmmEnabled); + } + + } else { + EPPING_HEADER *eppingHdr; + + eppingHdr = A_NETBUF_DATA(skb); + + if (IS_EPPING_PACKET(eppingHdr)) { + /* the stream ID is mapped to an access class */ + ac = eppingHdr->StreamNo_h; + /* some EPPING packets cannot be dropped no matter what access class it was + * sent on. We can change the packet tag to guarantee it will not get dropped */ + if (IS_EPING_PACKET_NO_DROP(eppingHdr)) { + htc_tag = AR6K_CONTROL_PKT_TAG; + } + + if (ac == HCI_TRANSPORT_STREAM_NUM) { + /* pass this to HCI */ +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + if (!hci_test_send(ar,skb)) { + return 0; + } +#endif + /* set AC to discard this skb */ + ac = AC_NOT_MAPPED; + } else { + /* a quirk of linux, the payload of the frame is 32-bit aligned and thus the addition + * of the HTC header will mis-align the start of the HTC frame, so we add some + * padding which will be stripped off in the target */ + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); + } + } + + } else { + /* not a ping packet, drop it */ + ac = AC_NOT_MAPPED; + } + } + + } while (false); + + /* did we succeed ? */ + if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) { + /* cleanup and exit */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + return 0; + } + + cookie = NULL; + + /* take the lock to protect driver data */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + do { + + if (checkAdHocPsMapping) { + eid = ar6000_ibss_map_epid(skb, dev, &mapNo); + }else { + eid = arAc2EndpointID (ar, ac); + } + /* validate that the endpoint is connected */ + if (eid == 0 || eid == ENDPOINT_UNUSED ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" eid %d is NOT mapped!\n", eid)); + break; + } + /* allocate resource for this packet */ + cookie = ar6000_alloc_cookie(ar); + + if (cookie != NULL) { + /* update counts while the lock is held */ + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + } while (false); + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)skb; + cookie->arc_bp[1] = mapNo; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb), + eid, + htc_tag); + +#ifdef DEBUG + if (debugdriver >= 3) { + ar6000_dump_skb(skb); + } +#endif +#ifdef HTC_TEST_SEND_PKTS + DoHTCSendPktsTest(ar,mapNo,eid,skb); +#endif + /* HTC interface is asynchronous, if this fails, cleanup will happen in + * the ar6000_tx_complete callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + } else { + /* no packet to send, cleanup */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + } + + return 0; +} + +int +ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + struct ar_cookie *cookie; + HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; + + cookie = NULL; + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* For now we send ACL on BE endpoint: We can also have a dedicated EP */ + eid = arAc2EndpointID (ar, 0); + /* allocate resource for this packet */ + cookie = ar6000_alloc_cookie(ar); + + if (cookie != NULL) { + /* update counts while the lock is held */ + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)skb; + cookie->arc_bp[1] = 0; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb), + eid, + AR6K_DATA_PKT_TAG); + + /* HTC interface is asynchronous, if this fails, cleanup will happen in + * the ar6000_tx_complete callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + } else { + /* no packet to send, cleanup */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + } + return 0; +} + + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +static void +tvsub(register struct timeval *out, register struct timeval *in) +{ + if((out->tv_usec -= in->tv_usec) < 0) { + out->tv_sec--; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +void +applyAPTCHeuristics(struct ar6_softc *ar) +{ + u32 duration; + u32 numbytes; + u32 throughput; + struct timeval ts; + int status; + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) { + do_gettimeofday(&ts); + tvsub(&ts, &aptcTR.samplingTS); + duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */ + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; + + if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) { + /* Initialize the time stamp and byte count */ + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; + do_gettimeofday(&aptcTR.samplingTS); + + /* Calculate and decide based on throughput thresholds */ + throughput = ((numbytes * 8) / duration); + if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) { + /* Disable Sleep and schedule a timer */ + A_ASSERT(ar->arWmiReady == true); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER); + AR6000_SPIN_LOCK(&ar->arLock, 0); + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); + aptcTR.timerScheduled = true; + } + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); +} +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP; + bool stopNet = false; + HTC_ENDPOINT_ID Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket); + + do { + + if (bypasswmi) { + int accessClass; + + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { + /* don't drop special control packets */ + break; + } + + accessClass = arEndpoint2Ac(ar,Endpoint); + /* for endpoint ping testing drop Best Effort and Background */ + if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) { + action = HTC_SEND_FULL_DROP; + stopNet = false; + } else { + /* keep but stop the netqueues */ + stopNet = true; + } + break; + } + + if (Endpoint == ar->arControlEp) { + /* under normal WMI if this is getting full, then something is running rampant + * the host should not be exhausting the WMI queue with too many commands + * the only exception to this is during testing using endpointping */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* set flag to handle subsequent messages */ + ar->arWMIControlEpFull = true; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n")); + /* no need to stop the network */ + stopNet = false; + break; + } + + /* if we get here, we are dealing with data endpoints getting full */ + + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { + /* don't drop control packets issued on ANY data endpoint */ + break; + } + + if (ar->arNetworkType == ADHOC_NETWORK) { + /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to + * continue, however we should stop the network */ + stopNet = true; + break; + } + /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest + * active stream */ + if (ar->arAcStreamPriMap[arEndpoint2Ac(ar,Endpoint)] < ar->arHiAcStreamActivePri && + ar->arCookieCount <= MAX_HI_COOKIE_NUM) { + /* this stream's priority is less than the highest active priority, we + * give preference to the highest priority stream by directing + * HTC to drop the packet that overflowed */ + action = HTC_SEND_FULL_DROP; + /* since we are dropping packets, no need to stop the network */ + stopNet = false; + break; + } + + } while (false); + + if (stopNet) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + ar->arNetQueueStopped = true; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + /* one of the data endpoints queues is getting full..need to stop network stack + * the queue will resume in ar6000_tx_complete() */ + netif_stop_queue(ar->arNetDev); + } + + return action; +} + + +static void +ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + u32 mapNo = 0; + int status; + struct ar_cookie * ar_cookie; + HTC_ENDPOINT_ID eid; + bool wakeEvent = false; + struct sk_buff_head skb_queue; + struct htc_packet *pPacket; + struct sk_buff *pktSkb; + bool flushing = false; + + skb_queue_head_init(&skb_queue); + + /* lock the driver as we update internal state */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* reap completed packets */ + while (!HTC_QUEUE_EMPTY(pPacketQueue)) { + + pPacket = HTC_PACKET_DEQUEUE(pPacketQueue); + + ar_cookie = (struct ar_cookie *)pPacket->pPktContext; + A_ASSERT(ar_cookie); + + status = pPacket->Status; + pktSkb = (struct sk_buff *)ar_cookie->arc_bp[0]; + eid = pPacket->Endpoint; + mapNo = ar_cookie->arc_bp[1]; + + A_ASSERT(pktSkb); + A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(pktSkb)); + + /* add this to the list, use faster non-lock API */ + __skb_queue_tail(&skb_queue,pktSkb); + + if (!status) { + A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_tx_complete skb=0x%lx data=0x%lx len=0x%x eid=%d ", + (unsigned long)pktSkb, (unsigned long)pPacket->pBuffer, + pPacket->ActualLength, + eid)); + + ar->arTxPending[eid]--; + + if ((eid != ar->arControlEp) || bypasswmi) { + ar->arTotalTxDataPending--; + } + + if (eid == ar->arControlEp) + { + if (ar->arWMIControlEpFull) { + /* since this packet completed, the WMI EP is no longer full */ + ar->arWMIControlEpFull = false; + } + + if (ar->arTxPending[eid] == 0) { + wakeEvent = true; + } + } + + if (status) { + if (status == A_ECANCELED) { + /* a packet was flushed */ + flushing = true; + } + AR6000_STAT_INC(ar, tx_errors); + if (status != A_NO_RESOURCE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() -TX ERROR, status: 0x%x\n", __func__, + status)); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n")); + flushing = false; + AR6000_STAT_INC(ar, tx_packets); + ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb); +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + aptcTR.bytesTransmitted += a_netbuf_to_len(pktSkb); + applyAPTCHeuristics(ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + } + + // TODO this needs to be looked at + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable + && (eid != ar->arControlEp) && mapNo) + { + mapNo --; + ar->arNodeMap[mapNo].txPending --; + + if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) { + u32 i; + for (i = ar->arNodeNum; i > 0; i --) { + if (!ar->arNodeMap[i - 1].txPending) { + A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping)); + ar->arNodeNum --; + } else { + break; + } + } + } + } + + ar6000_free_cookie(ar, ar_cookie); + + if (ar->arNetQueueStopped) { + ar->arNetQueueStopped = false; + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + /* lock is released, we can freely call other kernel APIs */ + + /* free all skbs in our local list */ + while (!skb_queue_empty(&skb_queue)) { + /* use non-lock version */ + pktSkb = __skb_dequeue(&skb_queue); + A_NETBUF_FREE(pktSkb); + } + + if ((ar->arConnected == true) || bypasswmi) { + if (!flushing) { + /* don't wake the queue if we are flushing, other wise it will just + * keep queueing packets, which will keep failing */ + netif_wake_queue(ar->arNetDev); + } + } + + if (wakeEvent) { + wake_up(&arEvent); + } + +} + +sta_t * +ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr) +{ + sta_t *conn = NULL; + u8 i, max_conn; + + switch(ar->arNetworkType) { + case AP_NETWORK: + max_conn = AP_MAX_NUM_STA; + break; + default: + max_conn=0; + break; + } + + for (i = 0; i < max_conn; i++) { + if (IEEE80211_ADDR_EQ(node_addr, ar->sta_list[i].mac)) { + conn = &ar->sta_list[i]; + break; + } + } + + return conn; +} + +sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid) +{ + sta_t *conn = NULL; + u8 ctr; + + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + if (ar->sta_list[ctr].aid == aid) { + conn = &ar->sta_list[ctr]; + break; + } + } + return conn; +} + +/* + * Receive event handler. This is called by HTC when a packet is received + */ +int pktcount; +static void +ar6000_rx(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext; + int minHdrLen; + u8 containsDot11Hdr = 0; + int status = pPacket->Status; + HTC_ENDPOINT_ID ept = pPacket->Endpoint; + + A_ASSERT((status) || + (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d", + (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer, + pPacket->ActualLength, status)); + if (status) { + if (status != A_ECANCELED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status)); + } + } + + /* take lock to protect buffer counts + * and adaptive power throughput state */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (!status) { + AR6000_STAT_INC(ar, rx_packets); + ar->arNetStats.rx_bytes += pPacket->ActualLength; +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + aptcTR.bytesReceived += a_netbuf_to_len(skb); + applyAPTCHeuristics(ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); + A_NETBUF_PULL(skb, HTC_HEADER_LEN); + +#ifdef DEBUG + if (debugdriver >= 2) { + ar6000_dump_skb(skb); + } +#endif /* DEBUG */ + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + skb->dev = ar->arNetDev; + if (status) { + AR6000_STAT_INC(ar, rx_errors); + A_NETBUF_FREE(skb); + } else if (ar->arWmiEnabled == true) { + if (ept == ar->arControlEp) { + /* + * this is a wmi control msg + */ +#ifdef CONFIG_PM + ar6000_check_wow_status(ar, skb, true); +#endif /* CONFIG_PM */ + wmi_control_rx(ar->arWmi, skb); + } else { + WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb); + bool is_amsdu; + u8 tid; + + /* + * This check can be removed if after a while we do not + * see the warning. For now we leave it to ensure + * we drop these frames accordingly in case the + * target generates them for some reason. These + * were used for an internal PAL but that's not + * used or supported anymore. These frames should + * not come up from the target. + */ + if (WARN_ON(WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == + WMI_DATA_HDR_DATA_TYPE_ACL)) { + AR6000_STAT_INC(ar, rx_errors); + A_NETBUF_FREE(skb); + return; + } + +#ifdef CONFIG_PM + ar6000_check_wow_status(ar, NULL, false); +#endif /* CONFIG_PM */ + /* + * this is a wmi data packet + */ + // NWF + + if (processDot11Hdr) { + minHdrLen = sizeof(WMI_DATA_HDR) + sizeof(struct ieee80211_frame) + sizeof(ATH_LLC_SNAP_HDR); + } else { + minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR); + } + + /* In the case of AP mode we may receive NULL data frames + * that do not have LLC hdr. They are 16 bytes in size. + * Allow these frames in the AP mode. + * ACL data frames don't follow ethernet frame bounds for + * min length + */ + if (ar->arNetworkType != AP_NETWORK && + ((pPacket->ActualLength < minHdrLen) || + (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE))) + { + /* + * packet is too short or too long + */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("TOO SHORT or TOO LONG\n")); + AR6000_STAT_INC(ar, rx_errors); + AR6000_STAT_INC(ar, rx_length_errors); + A_NETBUF_FREE(skb); + } else { + u16 seq_no; + u8 meta_type; + +#if 0 + /* Access RSSI values here */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("RSSI %d\n", + ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi)); +#endif + /* Get the Power save state of the STA */ + if (ar->arNetworkType == AP_NETWORK) { + sta_t *conn = NULL; + u8 psState=0,prevPsState; + ATH_MAC_HDR *datap=NULL; + u16 offset; + + meta_type = WMI_DATA_HDR_GET_META(dhdr); + + psState = (((WMI_DATA_HDR *)A_NETBUF_DATA(skb))->info + >> WMI_DATA_HDR_PS_SHIFT) & WMI_DATA_HDR_PS_MASK; + + offset = sizeof(WMI_DATA_HDR); + + switch (meta_type) { + case 0: + break; + case WMI_META_VERSION_1: + offset += sizeof(WMI_RX_META_V1); + break; + case WMI_META_VERSION_2: + offset += sizeof(WMI_RX_META_V2); + break; + default: + break; + } + + datap = (ATH_MAC_HDR *)(A_NETBUF_DATA(skb)+offset); + conn = ieee80211_find_conn(ar, datap->srcMac); + + if (conn) { + /* if there is a change in PS state of the STA, + * take appropriate steps. + * 1. If Sleep-->Awake, flush the psq for the STA + * Clear the PVB for the STA. + * 2. If Awake-->Sleep, Starting queueing frames + * the STA. + */ + prevPsState = STA_IS_PWR_SLEEP(conn); + if (psState) { + STA_SET_PWR_SLEEP(conn); + } else { + STA_CLR_PWR_SLEEP(conn); + } + + if (prevPsState ^ STA_IS_PWR_SLEEP(conn)) { + + if (!STA_IS_PWR_SLEEP(conn)) { + + A_MUTEX_LOCK(&conn->psqLock); + while (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { + struct sk_buff *skb=NULL; + + skb = A_NETBUF_DEQUEUE(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + ar6000_data_tx(skb,ar->arNetDev); + A_MUTEX_LOCK(&conn->psqLock); + } + A_MUTEX_UNLOCK(&conn->psqLock); + /* Clear the PVB for this STA */ + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); + } + } + } else { + /* This frame is from a STA that is not associated*/ + A_ASSERT(false); + } + + /* Drop NULL data frames here */ + if((pPacket->ActualLength < minHdrLen) || + (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE)) { + A_NETBUF_FREE(skb); + goto rx_done; + } + } + + is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false; + tid = WMI_DATA_HDR_GET_UP(dhdr); + seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr); + meta_type = WMI_DATA_HDR_GET_META(dhdr); + containsDot11Hdr = WMI_DATA_HDR_GET_DOT11(dhdr); + + wmi_data_hdr_remove(ar->arWmi, skb); + + switch (meta_type) { + case WMI_META_VERSION_1: + { + WMI_RX_META_V1 *pMeta = (WMI_RX_META_V1 *)A_NETBUF_DATA(skb); + A_PRINTF("META %d %d %d %d %x\n", pMeta->status, pMeta->rix, pMeta->rssi, pMeta->channel, pMeta->flags); + A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V1)); + break; + } + case WMI_META_VERSION_2: + { + WMI_RX_META_V2 *pMeta = (WMI_RX_META_V2 *)A_NETBUF_DATA(skb); + if(pMeta->csumFlags & 0x1){ + skb->ip_summed=CHECKSUM_COMPLETE; + skb->csum=(pMeta->csum); + } + A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V2)); + break; + } + default: + break; + } + + A_ASSERT(status == 0); + + /* NWF: print the 802.11 hdr bytes */ + if(containsDot11Hdr) { + status = wmi_dot11_hdr_remove(ar->arWmi,skb); + } else if(!is_amsdu) { + status = wmi_dot3_2_dix(skb); + } + + if (status) { + /* Drop frames that could not be processed (lack of memory, etc.) */ + A_NETBUF_FREE(skb); + goto rx_done; + } + + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) { + if (ar->arNetworkType == AP_NETWORK) { + struct sk_buff *skb1 = NULL; + ATH_MAC_HDR *datap; + + datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); + if (IEEE80211_IS_MULTICAST(datap->dstMac)) { + /* Bcast/Mcast frames should be sent to the OS + * stack as well as on the air. + */ + skb1 = skb_copy(skb,GFP_ATOMIC); + } else { + /* Search for a connected STA with dstMac as + * the Mac address. If found send the frame to + * it on the air else send the frame up the + * stack + */ + sta_t *conn = NULL; + conn = ieee80211_find_conn(ar, datap->dstMac); + + if (conn && ar->intra_bss) { + skb1 = skb; + skb = NULL; + } else if(conn && !ar->intra_bss) { + A_NETBUF_FREE(skb); + skb = NULL; + } + } + if (skb1) { + ar6000_data_tx(skb1, ar->arNetDev); + } + } + } + aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, is_amsdu, (void **)&skb); + ar6000_deliver_frames_to_nw_stack((void *) ar->arNetDev, (void *)skb); + } + } + } else { + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PULL(skb, EPPING_ALIGNMENT_PAD); + } + ar6000_deliver_frames_to_nw_stack((void *)ar->arNetDev, (void *)skb); + } + +rx_done: + + return; +} + +static void +ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf) +{ + struct sk_buff *skb = (struct sk_buff *)osbuf; + + if(skb) { + skb->dev = dev; + if ((skb->dev->flags & IFF_UP) == IFF_UP) { +#ifdef CONFIG_PM + ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false); +#endif /* CONFIG_PM */ + skb->protocol = eth_type_trans(skb, skb->dev); + /* + * If this routine is called on a ISR (Hard IRQ) or DSR (Soft IRQ) + * or tasklet use the netif_rx to deliver the packet to the stack + * netif_rx will queue the packet onto the receive queue and mark + * the softirq thread has a pending action to complete. Kernel will + * schedule the softIrq kernel thread after processing the DSR. + * + * If this routine is called on a process context, use netif_rx_ni + * which will schedle the softIrq kernel thread after queuing the packet. + */ + if (in_interrupt()) { + netif_rx(skb); + } else { + netif_rx_ni(skb); + } + } else { + A_NETBUF_FREE(skb); + } + } +} + +#if 0 +static void +ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf) +{ + struct sk_buff *skb = (struct sk_buff *)osbuf; + + if(skb) { + skb->dev = dev; + if ((skb->dev->flags & IFF_UP) == IFF_UP) { + skb->protocol = htons(ETH_P_CONTROL); + netif_rx(skb); + } else { + A_NETBUF_FREE(skb); + } + } +} +#endif + +static void +ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + void *osBuf; + int RxBuffers; + int buffersToRefill; + struct htc_packet *pPacket; + struct htc_packet_queue queue; + + buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - + HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint); + + if (buffersToRefill <= 0) { + /* fast return, nothing to fill */ + return; + } + + INIT_HTC_PACKET_QUEUE(&queue); + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n", + buffersToRefill, Endpoint)); + + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { + osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE); + if (NULL == osBuf) { + break; + } + /* the HTC packet wrapper is at the head of the reserved area + * in the skb */ + pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); + /* set re-fill info */ + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint); + /* add to queue */ + HTC_PACKET_ENQUEUE(&queue,pPacket); + } + + if (!HTC_QUEUE_EMPTY(&queue)) { + /* add packets */ + HTCAddReceivePktMultiple(ar->arHtcTarget, &queue); + } + +} + + /* clean up our amsdu buffer list */ +static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar) +{ + struct htc_packet *pPacket; + void *osBuf; + + /* empty AMSDU buffer queue and free OS bufs */ + while (true) { + + AR6000_SPIN_LOCK(&ar->arLock, 0); + pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == pPacket) { + break; + } + + osBuf = pPacket->pPktContext; + if (NULL == osBuf) { + A_ASSERT(false); + break; + } + + A_NETBUF_FREE(osBuf); + } + +} + + + /* refill the amsdu buffer list */ +static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count) +{ + struct htc_packet *pPacket; + void *osBuf; + + while (Count > 0) { + osBuf = A_NETBUF_ALLOC(AR6000_AMSDU_BUFFER_SIZE); + if (NULL == osBuf) { + break; + } + /* the HTC packet wrapper is at the head of the reserved area + * in the skb */ + pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); + /* set re-fill info */ + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* put it in the list */ + HTC_PACKET_ENQUEUE(&ar->amsdu_rx_buffer_queue,pPacket); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + Count--; + } + +} + + /* callback to allocate a large receive buffer for a pending packet. This function is called when + * an HTC packet arrives whose length exceeds a threshold value + * + * We use a pre-allocated list of buffers of maximum AMSDU size (4K). Under linux it is more optimal to + * keep the allocation size the same to optimize cached-slab allocations. + * + * */ +static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length) +{ + struct htc_packet *pPacket = NULL; + struct ar6_softc *ar = (struct ar6_softc *)Context; + int refillCount = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length)); + + do { + + if (Length <= AR6000_BUFFER_SIZE) { + /* shouldn't be getting called on normal sized packets */ + A_ASSERT(false); + break; + } + + if (Length > AR6000_AMSDU_BUFFER_SIZE) { + A_ASSERT(false); + break; + } + + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* allocate a packet from the list */ + pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); + /* see if we need to refill again */ + refillCount = AR6000_MAX_AMSDU_RX_BUFFERS - HTC_PACKET_QUEUE_DEPTH(&ar->amsdu_rx_buffer_queue); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == pPacket) { + break; + } + /* set actual endpoint ID */ + pPacket->Endpoint = Endpoint; + + } while (false); + + if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) { + ar6000_refill_amsdu_rxbufs(ar,refillCount); + } + + return pPacket; +} + +static void +ar6000_set_multicast_list(struct net_device *dev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: Multicast filter not supported\n")); +} + +static struct net_device_stats * +ar6000_get_stats(struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + return &ar->arNetStats; +} + +void +ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + struct net_device *dev = ar->arNetDev; + + memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5])); + + ar->arPhyCapability = phyCap; + ar->arVersion.wlan_ver = sw_ver; + ar->arVersion.abi_ver = abi_ver; + + snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version), + "%u:%u:%u:%u", + (ar->arVersion.wlan_ver & 0xf0000000) >> 28, + (ar->arVersion.wlan_ver & 0x0f000000) >> 24, + (ar->arVersion.wlan_ver & 0x00ff0000) >> 16, + (ar->arVersion.wlan_ver & 0x0000ffff)); + + /* Indicate to the waiting thread that the ready event was received */ + ar->arWmiReady = true; + wake_up(&arEvent); +} + +void ar6000_install_static_wep_keys(struct ar6_softc *ar) +{ + u8 index; + u8 keyUsage; + + for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { + if (ar->arWepKeyList[index].arKeyLen) { + keyUsage = GROUP_USAGE; + if (index == ar->arDefTxKeyIndex) { + keyUsage |= TX_USAGE; + } + wmi_addKey_cmd(ar->arWmi, + index, + WEP_CRYPT, + keyUsage, + ar->arWepKeyList[index].arKeyLen, + NULL, + ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + } +} + +void +add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie, + u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) +{ + u8 free_slot=aid-1; + + memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN); + memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen); + ar->sta_list[free_slot].aid = aid; + ar->sta_list[free_slot].keymgmt = keymgmt; + ar->sta_list[free_slot].ucipher = ucipher; + ar->sta_list[free_slot].auth = auth; + ar->sta_list_index = ar->sta_list_index | (1 << free_slot); + ar->arAPStats.sta[free_slot].aid = aid; +} + +void +ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid, + u16 listenInterval, u16 beaconInterval, + NETWORK_TYPE networkType, u8 beaconIeLen, + u8 assocReqLen, u8 assocRespLen, + u8 *assocInfo) +{ + union iwreq_data wrqu; + int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos; + static const char *tag1 = "ASSOCINFO(ReqIEs="; + static const char *tag2 = "ASSOCRESPIE="; + static const char *beaconIetag = "BEACONIE="; + char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1]; + char *pos; + u8 key_op_ctrl; + unsigned long flags; + struct ieee80211req_key *ik; + CRYPTO_TYPE keyType = NONE_CRYPT; + + if(ar->arNetworkType & AP_NETWORK) { + struct net_device *dev = ar->arNetDev; + if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) { + ar->arACS = channel; + ik = &ar->ap_mode_bkey; + + switch(ar->arAuthMode) { + case NONE_AUTH: + if(ar->arPairwiseCrypto == WEP_CRYPT) { + ar6000_install_static_wep_keys(ar); + } +#ifdef WAPI_ENABLE + else if(ar->arPairwiseCrypto == WAPI_CRYPT) { + ap_set_wapi_key(ar, ik); + } +#endif + break; + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + switch (ik->ik_type) { + case IEEE80211_CIPHER_TKIP: + keyType = TKIP_CRYPT; + break; + case IEEE80211_CIPHER_AES_CCM: + keyType = AES_CRYPT; + break; + default: + goto skip_key; + } + wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE, + ik->ik_keylen, (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + + break; + } +skip_key: + ar->arConnected = true; + return; + } + + A_PRINTF("NEW STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n " + " AID=%d \n", bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5], channel); + switch ((listenInterval>>8)&0xFF) { + case OPEN_AUTH: + A_PRINTF("AUTH: OPEN\n"); + break; + case SHARED_AUTH: + A_PRINTF("AUTH: SHARED\n"); + break; + default: + A_PRINTF("AUTH: Unknown\n"); + break; + } + switch (listenInterval&0xFF) { + case WPA_PSK_AUTH: + A_PRINTF("KeyMgmt: WPA-PSK\n"); + break; + case WPA2_PSK_AUTH: + A_PRINTF("KeyMgmt: WPA2-PSK\n"); + break; + default: + A_PRINTF("KeyMgmt: NONE\n"); + break; + } + switch (beaconInterval) { + case AES_CRYPT: + A_PRINTF("Cipher: AES\n"); + break; + case TKIP_CRYPT: + A_PRINTF("Cipher: TKIP\n"); + break; + case WEP_CRYPT: + A_PRINTF("Cipher: WEP\n"); + break; +#ifdef WAPI_ENABLE + case WAPI_CRYPT: + A_PRINTF("Cipher: WAPI\n"); + break; +#endif + default: + A_PRINTF("Cipher: NONE\n"); + break; + } + + add_new_sta(ar, bssid, channel /*aid*/, + assocInfo /* WPA IE */, assocRespLen /* IE len */, + listenInterval&0xFF /* Keymgmt */, beaconInterval /* cipher */, + (listenInterval>>8)&0xFF /* auth alg */); + + /* Send event to application */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); + wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL); + /* In case the queue is stopped when we switch modes, this will + * wake it up + */ + netif_wake_queue(ar->arNetDev); + return; + } + + ar6k_cfg80211_connect_event(ar, channel, bssid, + listenInterval, beaconInterval, + networkType, beaconIeLen, + assocReqLen, assocRespLen, + assocInfo); + + memcpy(ar->arBssid, bssid, sizeof(ar->arBssid)); + ar->arBssChannel = channel; + + A_PRINTF("AR6000 connected event on freq %d ", channel); + A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d" + " assocRespLen =%d\n", + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5], + listenInterval, beaconInterval, + beaconIeLen, assocReqLen, assocRespLen); + if (networkType & ADHOC_NETWORK) { + if (networkType & ADHOC_CREATOR) { + A_PRINTF("Network: Adhoc (Creator)\n"); + } else { + A_PRINTF("Network: Adhoc (Joiner)\n"); + } + } else { + A_PRINTF("Network: Infrastructure\n"); + } + + if ((ar->arNetworkType == INFRA_NETWORK)) { + wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); + } + + if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nBeaconIEs= ")); + + beacon_ie_pos = 0; + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", beaconIetag); + pos = buf + 9; + for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2)))) + { + assoc_resp_ie_pos = beaconIeLen + assocReqLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16) ; /* associd */ + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", tag2); + pos = buf + 12; + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocRespIEs= ")); + /* + * The Association Response Frame w.o. the WLAN header is delivered to + * the host, so skip over to the IEs + */ + for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++) + { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) { + /* + * assoc Request includes capability and listen interval. Skip these. + */ + assoc_req_ie_pos = beaconIeLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16); /* listen interval */ + + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", tag1); + pos = buf + 17; + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AssocReqIEs= ")); + for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN && + ar->user_saved_keys.keyOk == true) + { + key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC; + + if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) { + key_op_ctrl &= ~KEY_OP_INIT_RSC; + } else { + key_op_ctrl |= KEY_OP_INIT_RSC; + } + ar6000_reinstall_keys(ar, key_op_ctrl); + } + + netif_wake_queue(ar->arNetDev); + + /* Update connect & link status atomically */ + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = true; + ar->arConnectPending = false; + netif_carrier_on(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + /* reset the rx aggr state */ + aggr_reset_state(ar->aggr_cntxt); + reconnect_flag = 0; + + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) { + A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap)); + ar->arNodeNum = 0; + ar->arNexEpId = ENDPOINT_2; + } + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + +} + +void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num) +{ + A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1)); + ar->arNumDataEndPts = num; +} + +void +sta_cleanup(struct ar6_softc *ar, u8 i) +{ + struct sk_buff *skb; + + /* empty the queued pkts in the PS queue if any */ + A_MUTEX_LOCK(&ar->sta_list[i].psqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->sta_list[i].psq)) { + skb = A_NETBUF_DEQUEUE(&ar->sta_list[i].psq); + A_NETBUF_FREE(skb); + } + A_MUTEX_UNLOCK(&ar->sta_list[i].psqLock); + + /* Zero out the state fields */ + A_MEMZERO(&ar->arAPStats.sta[ar->sta_list[i].aid-1], sizeof(WMI_PER_STA_STAT)); + A_MEMZERO(&ar->sta_list[i].mac, ATH_MAC_LEN); + A_MEMZERO(&ar->sta_list[i].wpa_ie, IEEE80211_MAX_IE); + ar->sta_list[i].aid = 0; + ar->sta_list[i].flags = 0; + + ar->sta_list_index = ar->sta_list_index & ~(1 << i); + +} + +u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason) +{ + u8 i, removed=0; + + if(IS_MAC_NULL(mac)) { + return removed; + } + + if(IS_MAC_BCAST(mac)) { + A_PRINTF("DEL ALL STA\n"); + for(i=0; i < AP_MAX_NUM_STA; i++) { + if(!IS_MAC_NULL(ar->sta_list[i].mac)) { + sta_cleanup(ar, i); + removed = 1; + } + } + } else { + for(i=0; i < AP_MAX_NUM_STA; i++) { + if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) { + A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + " aid=%d REASON=%d\n", mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason); + + sta_cleanup(ar, i); + removed = 1; + break; + } + } + } + return removed; +} + +void +ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid, + u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus) +{ + u8 i; + unsigned long flags; + union iwreq_data wrqu; + + if(ar->arNetworkType & AP_NETWORK) { + union iwreq_data wrqu; + struct sk_buff *skb; + + if(!remove_sta(ar, bssid, protocolReasonStatus)) { + return; + } + + /* If there are no more associated STAs, empty the mcast PS q */ + if (ar->sta_list_index == 0) { + A_MUTEX_LOCK(&ar->mcastpsqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); + A_NETBUF_FREE(skb); + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* Clear the LSB of the BitMapCtl field of the TIM IE */ + if (ar->arWmiReady) { + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); + } + } + + if(!IS_MAC_BCAST(bssid)) { + /* Send event to application */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); + wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL); + } + + ar->arConnected = false; + return; + } + + ar6k_cfg80211_disconnect_event(ar, reason, bssid, + assocRespLen, assocInfo, + protocolReasonStatus); + + /* Send disconnect event to supplicant */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); + + /* it is necessary to clear the host-side rx aggregation state */ + aggr_reset_state(ar->aggr_cntxt); + + A_UNTIMEOUT(&ar->disconnect_timer); + + A_PRINTF("AR6000 disconnected"); + if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) { + A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nDisconnect Reason is %d", reason)); + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nProtocol Reason/Status Code is %d", protocolReasonStatus)); + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocResp Frame = %s", + assocRespLen ? " " : "NULL")); + for (i = 0; i < assocRespLen; i++) { + if (!(i % 0x10)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + /* + * If the event is due to disconnect cmd from the host, only they the target + * would stop trying to connect. Under any other condition, target would + * keep trying to connect. + * + */ + if( reason == DISCONNECT_CMD) + { + if ((!ar->arUserBssFilter) && (ar->arWmiReady)) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + } else { + ar->arConnectPending = true; + if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) || + ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) { + ar->arConnected = true; + return; + } + } + + if ((reason == NO_NETWORK_AVAIL) && (ar->arWmiReady)) + { + bss_t *pWmiSsidnode = NULL; + + /* remove the current associated bssid node */ + wmi_free_node (ar->arWmi, bssid); + + /* + * In case any other same SSID nodes are present + * remove it, since those nodes also not available now + */ + do + { + /* + * Find the nodes based on SSID and remove it + * NOTE :: This case will not work out for Hidden-SSID + */ + pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true); + + if (pWmiSsidnode) + { + wmi_free_node (ar->arWmi, pWmiSsidnode->ni_macaddr); + } + + } while (pWmiSsidnode); + } + + /* Update connect & link status atomically */ + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = false; + netif_carrier_off(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + + if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) { + reconnect_flag = 0; + } + + if (reason != CSERV_DISCONNECT) + { + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + } + + netif_stop_queue(ar->arNetDev); + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); + ar->arBssChannel = 0; + ar->arBeaconInterval = 0; + + ar6000_TxDataCleanup(ar); +} + +void +ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode) +{ + A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode); + ar->arRegCode = regCode; +} + +void +ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt) +{ + if(evt->status == 0) { + aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz); + } +} + +void +ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt) +{ + A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz); + if(evt->status == 0) { + } +} + +void +ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt) +{ + aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid); +} + +void register_pal_cb(ar6k_pal_config_t *palConfig_p) +{ + ar6k_pal_config_g = *palConfig_p; +} + +void +ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd) +{ + void *osbuf = NULL; + s8 i; + u8 size, *buf; + int ret = 0; + + size = cmd->evt_buf_sz + 4; + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + ret = A_NO_MEMORY; + A_PRINTF("Error in allocating netbuf \n"); + return; + } + + A_NETBUF_PUT(osbuf, size); + buf = (u8 *)A_NETBUF_DATA(osbuf); + /* First 2-bytes carry HCI event/ACL data type + * the next 2 are free + */ + *((short *)buf) = WMI_HCI_EVENT_EVENTID; + buf += sizeof(int); + memcpy(buf, cmd->buf, cmd->evt_buf_sz); + + ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf); + if(loghci) { + A_PRINTF_LOG("HCI Event From PAL <-- \n"); + for(i = 0; i < cmd->evt_buf_sz; i++) { + A_PRINTF_LOG("0x%02x ", cmd->buf[i]); + if((i % 10) == 0) { + A_PRINTF_LOG("\n"); + } + } + A_PRINTF_LOG("\n"); + A_PRINTF_LOG("==================================\n"); + } +} + +void +ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info) +{ +#if WIRELESS_EXT >= 18 + struct iw_pmkid_cand *pmkcand; +#else /* WIRELESS_EXT >= 18 */ + static const char *tag = "PRE-AUTH"; + char buf[128]; +#endif /* WIRELESS_EXT >= 18 */ + + union iwreq_data wrqu; + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("AR6000 Neighbor Report Event\n")); + for (i=0; i < numAps; info++, i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5])); + if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("preauth-cap")); + } + if (info->bssFlags & WMI_PMKID_VALID_BSS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,(" pmkid-valid\n")); + continue; /* we skip bss if the pmkid is already valid */ + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("\n")); + A_MEMZERO(&wrqu, sizeof(wrqu)); +#if WIRELESS_EXT >= 18 + pmkcand = A_MALLOC_NOWAIT(sizeof(struct iw_pmkid_cand)); + A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand)); + pmkcand->index = i; + pmkcand->flags = info->bssFlags; + memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand); + kfree(pmkcand); +#else /* WIRELESS_EXT >= 18 */ + snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", + tag, + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5], + i, info->bssFlags); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +#endif /* WIRELESS_EXT >= 18 */ + } +} + +void +ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) +{ + static const char *tag = "MLME-MICHAELMICFAILURE.indication"; + char buf[128]; + union iwreq_data wrqu; + + /* + * For AP case, keyid will have aid of STA which sent pkt with + * MIC error. Use this aid to get MAC & send it to hostapd. + */ + if (ar->arNetworkType == AP_NETWORK) { + sta_t *s = ieee80211_find_conn_for_aid(ar, (keyid >> 2)); + if(!s){ + A_PRINTF("AP TKIP MIC error received from Invalid aid / STA not found =%d\n", keyid); + return; + } + A_PRINTF("AP TKIP MIC error received from aid=%d\n", keyid); + snprintf(buf,sizeof(buf), "%s addr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + tag, s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]); + } else { + + ar6k_cfg80211_tkip_micerr_event(ar, keyid, ismcast); + + A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n", + keyid & 0x3, ismcast ? "multi": "uni"); + snprintf(buf, sizeof(buf), "%s(keyid=%d %sicast)", tag, keyid & 0x3, + ismcast ? "mult" : "un"); + } + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +} + +void +ar6000_scanComplete_event(struct ar6_softc *ar, int status) +{ + + ar6k_cfg80211_scanComplete_event(ar, status); + + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + if (ar->scan_triggered) { + if (status== 0) { + union iwreq_data wrqu; + A_MEMZERO(&wrqu, sizeof(wrqu)); + wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL); + } + ar->scan_triggered = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,( "AR6000 scan complete: %d\n", status)); +} + +void +ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + u8 ac; + + if(ar->arNetworkType == AP_NETWORK) { + WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr; + WMI_AP_MODE_STAT *ap = &ar->arAPStats; + + if (len < sizeof(*p)) { + return; + } + + for(ac=0;acsta[ac].tx_bytes += p->sta[ac].tx_bytes; + ap->sta[ac].tx_pkts += p->sta[ac].tx_pkts; + ap->sta[ac].tx_error += p->sta[ac].tx_error; + ap->sta[ac].tx_discard += p->sta[ac].tx_discard; + ap->sta[ac].rx_bytes += p->sta[ac].rx_bytes; + ap->sta[ac].rx_pkts += p->sta[ac].rx_pkts; + ap->sta[ac].rx_error += p->sta[ac].rx_error; + ap->sta[ac].rx_discard += p->sta[ac].rx_discard; + } + + } else { + WMI_TARGET_STATS *pTarget = (WMI_TARGET_STATS *)ptr; + TARGET_STATS *pStats = &ar->arTargetStats; + + if (len < sizeof(*pTarget)) { + return; + } + + // Update the RSSI of the connected bss. + if (ar->arConnected) { + bss_t *pConnBss = NULL; + + pConnBss = wmi_find_node(ar->arWmi,ar->arBssid); + if (pConnBss) + { + pConnBss->ni_rssi = pTarget->cservStats.cs_aveBeacon_rssi; + pConnBss->ni_snr = pTarget->cservStats.cs_aveBeacon_snr; + wmi_node_return(ar->arWmi, pConnBss); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 updating target stats\n")); + pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets; + pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes; + pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts; + pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes; + pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts; + pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes; + pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts; + pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes; + pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt; + for(ac = 0; ac < WMM_NUM_AC; ac++) + pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac]; + pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors; + pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt; + pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt; + pStats->tx_mult_retry_cnt += pTarget->txrxStats.tx_stats.tx_mult_retry_cnt; + pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt; + pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate); + + pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets; + pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes; + pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts; + pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes; + pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts; + pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes; + pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts; + pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes; + pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt; + pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors; + pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr; + pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss; + pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err; + pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames; + pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate); + + + pStats->tkip_local_mic_failure + += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure; + pStats->tkip_counter_measures_invoked + += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked; + pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays; + pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors; + pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors; + pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays; + + pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt; + pStats->noise_floor_calibation = pTarget->noise_floor_calibation; + + pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt; + pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt; + pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt; + pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt; + pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr; + pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi; + + if (enablerssicompensation) { + pStats->cs_aveBeacon_rssi = + rssi_compensation_calc(ar, pStats->cs_aveBeacon_rssi); + } + pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec; + pStats->cs_snr = pTarget->cservStats.cs_snr; + pStats->cs_rssi = pTarget->cservStats.cs_rssi; + + pStats->lq_val = pTarget->lqVal; + + pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped; + pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups; + pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups; + pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded; + pStats->arp_received += pTarget->arpStats.arp_received; + pStats->arp_matched += pTarget->arpStats.arp_matched; + pStats->arp_replied += pTarget->arpStats.arp_replied; + + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } + } +} + +void +ar6000_rssiThreshold_event(struct ar6_softc *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi) +{ + USER_RSSI_THOLD userRssiThold; + + rssi = rssi + SIGNAL_QUALITY_NOISE_FLOOR; + + if (enablerssicompensation) { + rssi = rssi_compensation_calc(ar, rssi); + } + + /* Send an event to the app */ + userRssiThold.tag = ar->rssi_map[newThreshold].tag; + userRssiThold.rssi = rssi; + A_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, + userRssiThold.tag, userRssiThold.rssi); +} + + +void +ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source) +{ + if (source != APP_HB_CHALLENGE) { + /* This would ignore the replys that come in after their due time */ + if (cookie == ar->arHBChallengeResp.seqNum) { + ar->arHBChallengeResp.outstanding = false; + } + } +} + + +void +ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal) +{ + static const char * const errString[] = { + [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL", + [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND", + [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR", + [WMI_TARGET_BMISS] "WMI_TARGET_BMISS", + [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN" + }; + + A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal); + + /* One error is reported at a time, and errorval is a bitmask */ + if(errorVal & (errorVal - 1)) + return; + + A_PRINTF("AR6000 Error type = "); + switch(errorVal) + { + case WMI_TARGET_PM_ERR_FAIL: + case WMI_TARGET_KEY_NOT_FOUND: + case WMI_TARGET_DECRYPTION_ERR: + case WMI_TARGET_BMISS: + case WMI_PSDISABLE_NODE_JOIN: + A_PRINTF("%s\n", errString[errorVal]); + break; + default: + A_PRINTF("INVALID\n"); + break; + } + +} + + +void +ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication, + u8 statusCode, u8 *tspecSuggestion) +{ + WMM_TSPEC_IE *tspecIe; + + /* + * This is the TSPEC IE suggestion from AP. + * Suggestion provided by AP under some error + * cases, could be helpful for the host app. + * Check documentation. + */ + tspecIe = (WMM_TSPEC_IE *)tspecSuggestion; + + /* + * What do we do, if we get TSPEC rejection? One thought + * that comes to mind is implictly delete the pstream... + */ + A_PRINTF("AR6000 CAC notification. " + "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n", + ac, cacIndication, statusCode); +} + +void +ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, + u16 newChannel) +{ + A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n", + oldChannel, newChannel); +} + +#define AR6000_PRINT_BSSID(_pBss) do { \ + A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\ + (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\ + (_pBss)[4],(_pBss)[5]); \ +} while(0) + +void +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl) +{ + u8 i; + + A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n", + pTbl->numEntries, pTbl->roamMode); + for (i= 0; i < pTbl->numEntries; i++) { + A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i, + pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1], + pTbl->bssRoamInfo[i].bssid[2], + pTbl->bssRoamInfo[i].bssid[3], + pTbl->bssRoamInfo[i].bssid[4], + pTbl->bssRoamInfo[i].bssid[5]); + A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d" + " BIAS %d\n", + pTbl->bssRoamInfo[i].rssi, + pTbl->bssRoamInfo[i].rssidt, + pTbl->bssRoamInfo[i].last_rssi, + pTbl->bssRoamInfo[i].util, + pTbl->bssRoamInfo[i].roam_util, + pTbl->bssRoamInfo[i].bias); + } +} + +void +ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply) +{ + u8 i,j; + + /*Each event now contains exactly one filter, see bug 26613*/ + A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters); + A_PRINTF("wow mode = %s host mode = %s\n", + (wow_reply->wow_mode == 0? "disabled":"enabled"), + (wow_reply->host_mode == 1 ? "awake":"asleep")); + + + /*If there are no patterns, the reply will only contain generic + WoW information. Pattern information will exist only if there are + patterns present. Bug 26716*/ + + /* If this event contains pattern information, display it*/ + if (wow_reply->this_filter_num) { + i=0; + A_PRINTF("id=%d size=%d offset=%d\n", + wow_reply->wow_filters[i].wow_filter_id, + wow_reply->wow_filters[i].wow_filter_size, + wow_reply->wow_filters[i].wow_filter_offset); + A_PRINTF("wow pattern = "); + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]); + } + + A_PRINTF("\nwow mask = "); + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]); + } + A_PRINTF("\n"); + } +} + +/* + * Report the Roaming related data collected on the target + */ +void +ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p) +{ + A_PRINTF("Disconnect Data : BSSID: "); + AR6000_PRINT_BSSID(p->disassoc_bssid); + A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n", + p->disassoc_bss_rssi,p->disassoc_time, + p->no_txrx_time); + A_PRINTF("Connect Data: BSSID: "); + AR6000_PRINT_BSSID(p->assoc_bssid); + A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n", + p->assoc_bss_rssi,p->assoc_time, + p->allow_txrx_time); +} + +void +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p) +{ + switch (p->roamDataType) { + case ROAM_DATA_TIME: + ar6000_display_roam_time(&p->u.roamTime); + break; + default: + break; + } +} + +void +ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len) +{ + struct sk_buff *skb; + WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap; + + + if (!ar->arMgmtFilter) { + return; + } + if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) && + (bih->frameType != BEACON_FTYPE)) || + ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) && + (bih->frameType != PROBERESP_FTYPE))) + { + return; + } + + if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) { + + A_NETBUF_PUT(skb, len); + memcpy(A_NETBUF_DATA(skb), datap, len); + skb->dev = ar->arNetDev; + memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6); + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(0x0019); + netif_rx(skb); + } +} + +u32 wmiSendCmdNum; + +int +ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + int status = 0; + struct ar_cookie *cookie = NULL; + int i; +#ifdef CONFIG_PM + if (ar->arWowState != WLAN_WOW_STATE_NONE) { + A_NETBUF_FREE(osbuf); + return A_EACCES; + } +#endif /* CONFIG_PM */ + /* take lock to protect ar6000_alloc_cookie() */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + do { + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar_contrstatus = ol_tx: skb=0x%lx, len=0x%x eid =%d\n", + (unsigned long)osbuf, A_NETBUF_LEN(osbuf), eid)); + + if (ar->arWMIControlEpFull && (eid == ar->arControlEp)) { + /* control endpoint is full, don't allocate resources, we + * are just going to drop this packet */ + cookie = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" WMI Control EP full, dropping packet : 0x%lX, len:%d \n", + (unsigned long)osbuf, A_NETBUF_LEN(osbuf))); + } else { + cookie = ar6000_alloc_cookie(ar); + } + + if (cookie == NULL) { + status = A_NO_MEMORY; + break; + } + + if(logWmiRawMsgs) { + A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum); + for(i = 0; i < a_netbuf_to_len(osbuf); i++) + A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]); + A_PRINTF("\n"); + } + + wmiSendCmdNum++; + + } while (false); + + if (cookie != NULL) { + /* got a structure to send it out on */ + ar->arTxPending[eid]++; + + if (eid != ar->arControlEp) { + ar->arTotalTxDataPending++; + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)osbuf; + cookie->arc_bp[1] = 0; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(osbuf), + A_NETBUF_LEN(osbuf), + eid, + AR6K_CONTROL_PKT_TAG); + /* this interface is asynchronous, if there is an error, cleanup will happen in the + * TX completion callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + status = 0; + } + + if (status) { + A_NETBUF_FREE(osbuf); + } + return status; +} + +/* indicate tx activity or inactivity on a WMI stream */ +void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + HTC_ENDPOINT_ID eid ; + int i; + + if (ar->arWmiEnabled) { + eid = arAc2EndpointID(ar, TrafficClass); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + ar->arAcStreamActive[TrafficClass] = Active; + + if (Active) { + /* when a stream goes active, keep track of the active stream with the highest priority */ + + if (ar->arAcStreamPriMap[TrafficClass] > ar->arHiAcStreamActivePri) { + /* set the new highest active priority */ + ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[TrafficClass]; + } + + } else { + /* when a stream goes inactive, we may have to search for the next active stream + * that is the highest priority */ + + if (ar->arHiAcStreamActivePri == ar->arAcStreamPriMap[TrafficClass]) { + + /* the highest priority stream just went inactive */ + + /* reset and search for the "next" highest "active" priority stream */ + ar->arHiAcStreamActivePri = 0; + for (i = 0; i < WMM_NUM_AC; i++) { + if (ar->arAcStreamActive[i]) { + if (ar->arAcStreamPriMap[i] > ar->arHiAcStreamActivePri) { + /* set the new highest active priority */ + ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[i]; + } + } + } + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + } else { + /* for mbox ping testing, the traffic class is mapped directly as a stream ID, + * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c + * convert the stream ID to a endpoint */ + eid = arAc2EndpointID(ar, TrafficClass); + } + + /* notify HTC, this may cause credit distribution changes */ + + HTCIndicateActivityChange(ar->arHtcTarget, + eid, + Active); + +} + +void +ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + + WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr; + WMI_BTCOEX_CONFIG_EVENT *pArbtcoexConfig =&ar->arBtcoexConfig; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); + + A_PRINTF("received config event\n"); + pArbtcoexConfig->btProfileType = pBtcoexConfig->btProfileType; + pArbtcoexConfig->linkId = pBtcoexConfig->linkId; + + switch (pBtcoexConfig->btProfileType) { + case WMI_BTCOEX_BT_PROFILE_SCO: + memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd, + sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_A2DP: + memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd, + sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_ACLCOEX: + memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig, + sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE: + memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd, + sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + break; + } + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } +} + +void +ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); + + memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT)); + + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } + +} +module_init(ar6000_init_module); +module_exit(ar6000_cleanup_module); + +/* Init cookie queue */ +static void +ar6000_cookie_init(struct ar6_softc *ar) +{ + u32 i; + + ar->arCookieList = NULL; + ar->arCookieCount = 0; + + A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem)); + + for (i = 0; i < MAX_COOKIE_NUM; i++) { + ar6000_free_cookie(ar, &s_ar_cookie_mem[i]); + } +} + +/* cleanup cookie queue */ +static void +ar6000_cookie_cleanup(struct ar6_softc *ar) +{ + /* It is gone .... */ + ar->arCookieList = NULL; + ar->arCookieCount = 0; +} + +/* Init cookie queue */ +static void +ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie) +{ + /* Insert first */ + A_ASSERT(ar != NULL); + A_ASSERT(cookie != NULL); + + cookie->arc_list_next = ar->arCookieList; + ar->arCookieList = cookie; + ar->arCookieCount++; +} + +/* cleanup cookie queue */ +static struct ar_cookie * +ar6000_alloc_cookie(struct ar6_softc *ar) +{ + struct ar_cookie *cookie; + + cookie = ar->arCookieList; + if(cookie != NULL) + { + ar->arCookieList = cookie->arc_list_next; + ar->arCookieCount--; + } + + return cookie; +} + +void +ar6000_tx_retry_err_event(void *devt) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Tx retries reach maximum!\n")); +} + +void +ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr) +{ + WMI_SNR_THRESHOLD_EVENT event; + + event.range = newThreshold; + event.snr = snr; +} + +void +ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq)); +} + + + +u32 a_copy_to_user(void *to, const void *from, u32 n) +{ + return(copy_to_user(to, from, n)); +} + +u32 a_copy_from_user(void *to, const void *from, u32 n) +{ + return(copy_from_user(to, from, n)); +} + + +int +ar6000_get_driver_cfg(struct net_device *dev, + u16 cfgParam, + void *result) +{ + + int ret = 0; + + switch(cfgParam) + { + case AR6000_DRIVER_CFG_GET_WLANNODECACHING: + *((u32 *)result) = wlanNodeCaching; + break; + case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS: + *((u32 *)result) = logWmiRawMsgs; + break; + default: + ret = EINVAL; + break; + } + + return ret; +} + +void +ar6000_keepalive_rx(void *devt, u8 configured) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arKeepaliveConfigured = configured; + wake_up(&arEvent); +} + +void +ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList, + u8 *bssidList) +{ + u8 i, j; + + A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID); + + for (i = 0; i < numPMKID; i++) { + A_PRINTF("\nBSSID %d ", i); + for (j = 0; j < ATH_MAC_LEN; j++) { + A_PRINTF("%2.2x", bssidList[j]); + } + bssidList += (ATH_MAC_LEN + WMI_PMKID_LEN); + A_PRINTF("\nPMKID %d ", i); + for (j = 0; j < WMI_PMKID_LEN; j++) { + A_PRINTF("%2.2x", pmkidList->pmkid[j]); + } + pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN + + WMI_PMKID_LEN); + } +} + +void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid) +{ + sta_t *conn=NULL; + bool isPsqEmpty = false; + + conn = ieee80211_find_conn_for_aid(ar, aid); + + /* If the PS q for this STA is not empty, dequeue and send a pkt from + * the head of the q. Also update the More data bit in the WMI_DATA_HDR + * if there are more pkts for this STA in the PS q. If there are no more + * pkts for this STA, update the PVB for this STA. + */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + + if (isPsqEmpty) { + /* TODO:No buffered pkts for this STA. Send out a NULL data frame */ + } else { + struct sk_buff *skb = NULL; + + A_MUTEX_LOCK(&conn->psqLock); + skb = A_NETBUF_DEQUEUE(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + /* Set the STA flag to PSPolled, so that the frame will go out */ + STA_SET_PS_POLLED(conn); + ar6000_data_tx(skb, ar->arNetDev); + STA_CLR_PS_POLLED(conn); + + /* Clear the PVB for this STA if the queue has become empty */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + + if (isPsqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); + } + } +} + +void ar6000_dtimexpiry_event(struct ar6_softc *ar) +{ + bool isMcastQueued = false; + struct sk_buff *skb = NULL; + + /* If there are no associated STAs, ignore the DTIM expiry event. + * There can be potential race conditions where the last associated + * STA may disconnect & before the host could clear the 'Indicate DTIM' + * request to the firmware, the firmware would have just indicated a DTIM + * expiry event. The race is between 'clear DTIM expiry cmd' going + * from the host to the firmware & the DTIM expiry event happening from + * the firmware to the host. + */ + if (ar->sta_list_index == 0) { + return; + } + + A_MUTEX_LOCK(&ar->mcastpsqLock); + isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + A_ASSERT(isMcastQueued == false); + + /* Flush the mcast psq to the target */ + /* Set the STA flag to DTIMExpired, so that the frame will go out */ + ar->DTIMExpired = true; + + A_MUTEX_LOCK(&ar->mcastpsqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + ar6000_data_tx(skb, ar->arNetDev); + + A_MUTEX_LOCK(&ar->mcastpsqLock); + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* Reset the DTIMExpired flag back to 0 */ + ar->DTIMExpired = false; + + /* Clear the LSB of the BitMapCtl field of the TIM IE */ + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); +} + +void +read_rssi_compensation_param(struct ar6_softc *ar) +{ + u8 *cust_data_ptr; + +//#define RSSICOMPENSATION_PRINT + +#ifdef RSSICOMPENSATION_PRINT + s16 i; + cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); + for (i=0; i<16; i++) { + A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr); + cust_data_ptr += 1; + } +#endif + + cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); + + rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff; + rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff; + rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff; + rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff; + rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff; + rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff; + rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12); + +#ifdef RSSICOMPENSATION_PRINT + A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID); + A_PRINTF("enable = 0x%x \n", rssi_compensation_param.enable); + A_PRINTF("bg_param_a = 0x%x and %d \n", rssi_compensation_param.bg_param_a, rssi_compensation_param.bg_param_a); + A_PRINTF("bg_param_b = 0x%x and %d \n", rssi_compensation_param.bg_param_b, rssi_compensation_param.bg_param_b); + A_PRINTF("a_param_a = 0x%x and %d \n", rssi_compensation_param.a_param_a, rssi_compensation_param.a_param_a); + A_PRINTF("a_param_b = 0x%x and %d \n", rssi_compensation_param.a_param_b, rssi_compensation_param.a_param_b); + A_PRINTF("Last 4 bytes = 0x%x \n", rssi_compensation_param.reserved); +#endif + + if (rssi_compensation_param.enable != 0x1) { + rssi_compensation_param.enable = 0; + } + + return; +} + +s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt) +{ + + if (freq > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); + rssi = rssi * rssi_compensation_param.a_param_a + totalPkt * rssi_compensation_param.a_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); + rssi = rssi * rssi_compensation_param.bg_param_a + totalPkt * rssi_compensation_param.bg_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + + return rssi; +} + +s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi) +{ + if (ar->arBssChannel > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); + rssi = rssi * rssi_compensation_param.a_param_a + rssi_compensation_param.a_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); + rssi = rssi * rssi_compensation_param.bg_param_a + rssi_compensation_param.bg_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + + return rssi; +} + +s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above) +{ + s16 i; + + if (ar->arBssChannel > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); + rssi = rssi * 100; + rssi = (rssi - rssi_compensation_param.a_param_b) / rssi_compensation_param.a_param_a; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); + + if (Above) { + for (i=95; i>=0; i--) { + if (rssi <= rssi_compensation_table[i]) { + rssi = 0 - i; + break; + } + } + } else { + for (i=0; i<=95; i++) { + if (rssi >= rssi_compensation_table[i]) { + rssi = 0 - i; + break; + } + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); + } + } + + return rssi; +} + +#ifdef WAPI_ENABLE +void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac) +{ + union iwreq_data wrqu; + char buf[20]; + + A_MEMZERO(buf, sizeof(buf)); + + strcpy(buf, "WAPI_REKEY"); + buf[10] = type; + memcpy(&buf[11], mac, ATH_MAC_LEN); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = 10+1+ATH_MAC_LEN; + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + + A_PRINTF("WAPI REKEY - %d - %02x:%02x\n", type, mac[4], mac[5]); +} +#endif + +static int +ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl) +{ + int status = 0; + struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik; + struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik; + CRYPTO_TYPE keyType = ar->user_saved_keys.keyType; + + if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) { + if (NONE_CRYPT == keyType) { + goto _reinstall_keys_out; + } + + if (uik->ik_keylen) { + status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix, + ar->user_saved_keys.keyType, PAIRWISE_USAGE, + uik->ik_keylen, (u8 *)&uik->ik_keyrsc, + uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG); + } + + } else { + status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata); + } + + if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) { + if (NONE_CRYPT == keyType) { + goto _reinstall_keys_out; + } + + if (bik->ik_keylen) { + status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix, + ar->user_saved_keys.keyType, GROUP_USAGE, + bik->ik_keylen, (u8 *)&bik->ik_keyrsc, + bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG); + } + } else { + status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata); + } + +_reinstall_keys_out: + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + + return status; +} + + +void +ar6000_dset_open_req( + void *context, + u32 id, + u32 targHandle, + u32 targReplyFn, + u32 targReplyArg) +{ +} + +void +ar6000_dset_close( + void *context, + u32 access_cookie) +{ + return; +} + +void +ar6000_dset_data_req( + void *context, + u32 accessCookie, + u32 offset, + u32 length, + u32 targBuf, + u32 targReplyFn, + u32 targReplyArg) +{ +} + +int +ar6000_ap_mode_profile_commit(struct ar6_softc *ar) +{ + WMI_CONNECT_CMD p; + unsigned long flags; + + /* No change in AP's profile configuration */ + if(ar->ap_profile_flag==0) { + A_PRINTF("COMMIT: No change in profile!!!\n"); + return -ENODATA; + } + + if(!ar->arSsidLen) { + A_PRINTF("SSID not set!!!\n"); + return -ECHRNG; + } + + switch(ar->arAuthMode) { + case NONE_AUTH: + if((ar->arPairwiseCrypto != NONE_CRYPT) && +#ifdef WAPI_ENABLE + (ar->arPairwiseCrypto != WAPI_CRYPT) && +#endif + (ar->arPairwiseCrypto != WEP_CRYPT)) { + A_PRINTF("Cipher not supported in AP mode Open auth\n"); + return -EOPNOTSUPP; + } + break; + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + break; + default: + A_PRINTF("This key mgmt type not supported in AP mode\n"); + return -EOPNOTSUPP; + } + + /* Update the arNetworkType */ + ar->arNetworkType = ar->arNextMode; + + A_MEMZERO(&p,sizeof(p)); + p.ssidLength = ar->arSsidLen; + memcpy(p.ssid,ar->arSsid,p.ssidLength); + p.channel = ar->arChannelHint; + p.networkType = ar->arNetworkType; + + p.dot11AuthMode = ar->arDot11AuthMode; + p.authMode = ar->arAuthMode; + p.pairwiseCryptoType = ar->arPairwiseCrypto; + p.pairwiseCryptoLen = ar->arPairwiseCryptoLen; + p.groupCryptoType = ar->arGroupCrypto; + p.groupCryptoLen = ar->arGroupCryptoLen; + p.ctrl_flags = ar->arConnectCtrlFlags; + + wmi_ap_profile_commit(ar->arWmi, &p); + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = true; + netif_carrier_on(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + ar->ap_profile_flag = 0; + return 0; +} + +int +ar6000_connect_to_ap(struct ar6_softc *ar) +{ + /* The ssid length check prevents second "essid off" from the user, + to be treated as a connect cmd. The second "essid off" is ignored. + */ + if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK) + { + int status; + if((ADHOC_NETWORK != ar->arNetworkType) && + (NONE_AUTH==ar->arAuthMode) && + (WEP_CRYPT==ar->arPairwiseCrypto)) { + ar6000_install_static_wep_keys(ar); + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { + return -EIO; + } + } +#ifdef WAPI_ENABLE + if (ar->arWapiEnable) { + ar->arPairwiseCrypto = WAPI_CRYPT; + ar->arPairwiseCryptoLen = 0; + ar->arGroupCrypto = WAPI_CRYPT; + ar->arGroupCryptoLen = 0; + ar->arAuthMode = NONE_AUTH; + ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER; + } +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d\n", + ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen)); + reconnect_flag = 0; + /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn. + later set it back locally at the STA to 100/1000 TUs depending on the power mode */ + if ((ar->arNetworkType == INFRA_NETWORK)) { + wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0); + } + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + if (status) { + wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + return status; + } + + if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && + ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) + { + A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); + } + + ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; + + ar->arConnectPending = true; + return status; + } + return A_ERROR; +} + +int +ar6000_disconnect(struct ar6_softc *ar) +{ + if ((ar->arConnected == true) || (ar->arConnectPending == true)) { + wmi_disconnect_cmd(ar->arWmi); + /* + * Disconnect cmd is issued, clear connectPending. + * arConnected will be cleard in disconnect_event notification. + */ + ar->arConnectPending = false; + } + + return 0; +} + +int +ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie) +{ + sta_t *conn = NULL; + conn = ieee80211_find_conn(ar, wpaie->wpa_macaddr); + + A_MEMZERO(wpaie->wpa_ie, IEEE80211_MAX_IE); + A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE); + + if(conn) { + memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE); + } + + return 0; +} + +int +is_iwioctl_allowed(u8 mode, u16 cmd) +{ + if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) { + cmd -= SIOCSIWCOMMIT; + if(sioctl_filter[cmd] == 0xFF) return 0; + if(sioctl_filter[cmd] & mode) return 0; + } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) { + cmd -= SIOCIWFIRSTPRIV; + if(pioctl_filter[cmd] == 0xFF) return 0; + if(pioctl_filter[cmd] & mode) return 0; + } else { + return A_ERROR; + } + return A_ENOTSUP; +} + +int +is_xioctl_allowed(u8 mode, int cmd) +{ + if(sizeof(xioctl_filter)-1 < cmd) { + A_PRINTF("Filter for this cmd=%d not defined\n",cmd); + return 0; + } + if(xioctl_filter[cmd] == 0xFF) return 0; + if(xioctl_filter[cmd] & mode) return 0; + return A_ERROR; +} + +#ifdef WAPI_ENABLE +int +ap_set_wapi_key(struct ar6_softc *ar, void *ikey) +{ + struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey; + KEY_USAGE keyUsage = 0; + int status; + + if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) { + keyUsage = GROUP_USAGE; + } else { + keyUsage = PAIRWISE_USAGE; + } + A_PRINTF("WAPI_KEY: Type:%d ix:%d mac:%02x:%02x len:%d\n", + keyUsage, ik->ik_keyix, ik->ik_macaddr[4], ik->ik_macaddr[5], + ik->ik_keylen); + + status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage, + ik->ik_keylen, (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + + if (0 != status) { + return -EIO; + } + return 0; +} +#endif + +void ar6000_peer_event( + void *context, + u8 eventCode, + u8 *macAddr) +{ + u8 pos; + + for (pos=0;pos<6;pos++) + printk("%02x: ",*(macAddr+pos)); + printk("\n"); +} + +#ifdef HTC_TEST_SEND_PKTS +#define HTC_TEST_DUPLICATE 8 +static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb) +{ + struct ar_cookie *cookie; + struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE]; + struct sk_buff *new_skb; + int i; + int pkts = 0; + struct htc_packet_queue pktQueue; + EPPING_HEADER *eppingHdr; + + eppingHdr = A_NETBUF_DATA(dupskb); + + if (eppingHdr->Cmd_h == EPPING_CMD_NO_ECHO) { + /* skip test if this is already a tx perf test */ + return; + } + + for (i = 0; i < HTC_TEST_DUPLICATE; i++,pkts++) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + cookie = ar6000_alloc_cookie(ar); + if (cookie != NULL) { + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == cookie) { + break; + } + + new_skb = A_NETBUF_ALLOC(A_NETBUF_LEN(dupskb)); + + if (new_skb == NULL) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + ar6000_free_cookie(ar,cookie); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + break; + } + + A_NETBUF_PUT_DATA(new_skb, A_NETBUF_DATA(dupskb), A_NETBUF_LEN(dupskb)); + cookie->arc_bp[0] = (unsigned long)new_skb; + cookie->arc_bp[1] = MapNo; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(new_skb), + A_NETBUF_LEN(new_skb), + eid, + AR6K_DATA_PKT_TAG); + + cookieArray[i] = cookie; + + { + EPPING_HEADER *pHdr = (EPPING_HEADER *)A_NETBUF_DATA(new_skb); + pHdr->Cmd_h = EPPING_CMD_NO_ECHO; /* do not echo the packet */ + } + } + + if (pkts == 0) { + return; + } + + INIT_HTC_PACKET_QUEUE(&pktQueue); + + for (i = 0; i < pkts; i++) { + HTC_PACKET_ENQUEUE(&pktQueue,&cookieArray[i]->HtcPkt); + } + + HTCSendPktsMultiple(ar->arHtcTarget, &pktQueue); + +} +#endif + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +/* + * Add support for adding and removing a virtual adapter for soft AP. + * Some OS requires different adapters names for station and soft AP mode. + * To support these requirement, create and destroy a netdevice instance + * when the AP mode is operational. A full fledged support for virual device + * is not implemented. Rather a virtual interface is created and is linked + * with the existing physical device instance during the operation of the + * AP mode. + */ + +int ar6000_start_ap_interface(struct ar6_softc *ar) +{ + struct ar_virtual_interface *arApDev; + + /* Change net_device to point to AP instance */ + arApDev = (struct ar_virtual_interface *)ar->arApDev; + ar->arNetDev = arApDev->arNetDev; + + return 0; +} + +int ar6000_stop_ap_interface(struct ar6_softc *ar) +{ + struct ar_virtual_interface *arApDev; + + /* Change net_device to point to sta instance */ + arApDev = (struct ar_virtual_interface *)ar->arApDev; + if (arApDev) { + ar->arNetDev = arApDev->arStaNetDev; + } + + return 0; +} + + +int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname) +{ + struct net_device *dev; + struct ar_virtual_interface *arApDev; + + dev = alloc_etherdev(sizeof(struct ar_virtual_interface)); + if (dev == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n")); + return A_ERROR; + } + + ether_setup(dev); + init_netdev(dev, ap_ifname); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + + if (register_netdev(dev)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n")); + return A_ERROR; + } + + arApDev = netdev_priv(dev); + arApDev->arDev = ar; + arApDev->arNetDev = dev; + arApDev->arStaNetDev = ar->arNetDev; + + ar->arApDev = arApDev; + arApNetDev = dev; + + /* Copy the MAC address */ + memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN); + + return 0; +} + +int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname) +{ + /* Interface already added, need not proceed further */ + if (ar->arApDev != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n")); + return 0; + } + + if (ar6000_create_ap_interface(ar, ap_ifname) != 0) { + return A_ERROR; + } + + A_PRINTF("Add AP interface %s \n",ap_ifname); + + return ar6000_start_ap_interface(ar); +} + +int ar6000_remove_ap_interface(struct ar6_softc *ar) +{ + if (arApNetDev) { + ar6000_stop_ap_interface(ar); + + unregister_netdev(arApNetDev); + free_netdev(apApNetDev); + + A_PRINTF("Remove AP interface\n"); + } + ar->arApDev = NULL; + arApNetDev = NULL; + + + return 0; +} +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +EXPORT_SYMBOL(setupbtdev); +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c new file mode 100644 index 000000000000..1e0ace8b6d13 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c @@ -0,0 +1,626 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +/* + * Implementation of system power management + */ + +#include "ar6000_drv.h" +#include +#include +#include "wlan_config.h" + +#define WOW_ENABLE_MAX_INTERVAL 0 +#define WOW_SET_SCAN_PARAMS 0 + +extern unsigned int wmitimeout; +extern wait_queue_head_t arEvent; + +#undef ATH_MODULE_NAME +#define ATH_MODULE_NAME pm +#define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef DEBUG +static struct ath_debug_mask_description pm_debug_desc[] = { + { ATH_DEBUG_PM , "System power management"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm, + "pm", + "System Power Management", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_PM, + ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc), + pm_debug_desc); + +#endif /* DEBUG */ + +int ar6000_exit_cut_power_state(struct ar6_softc *ar); + +#ifdef CONFIG_PM +static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep) +{ + char buf[128]; + union iwreq_data wrqu; + + snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake"); + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +} + +static void ar6000_wow_resume(struct ar6_softc *ar) +{ + if (ar->arWowState!= WLAN_WOW_STATE_NONE) { + u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; + u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period; + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false}; + ar->arWowState = WLAN_WOW_STATE_NONE; + if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n")); + } +#if WOW_SET_SCAN_PARAMS + wmi_scanparams_cmd(ar->arWmi, fg_start_period, + ar->scParams.fg_end_period, + bg_period, + ar->scParams.minact_chdwell_time, + ar->scParams.maxact_chdwell_time, + ar->scParams.pas_chdwell_time, + ar->scParams.shortScanRatio, + ar->scParams.scanCtrlFlags, + ar->scParams.max_dfsch_act_time, + ar->scParams.maxact_scan_per_ssid); +#else + (void)fg_start_period; + (void)bg_period; +#endif + + +#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ + if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) { + } +#endif + ar6k_send_asleep_event_to_app(ar, false); + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume")); + } + ar->arWlanPowerState = WLAN_POWER_STATE_ON; +} + +static void ar6000_wow_suspend(struct ar6_softc *ar) +{ +#define WOW_LIST_ID 1 + if (ar->arNetworkType != AP_NETWORK) { + /* Setup WoW for unicast & Arp request for our own IP + disable background scan. Set listen interval into 1000 TUs + Enable keepliave for 110 seconds + */ + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + struct in_device *in_dev; + u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + int status; + WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; + WMI_DEL_WOW_PATTERN_CMD delWowCmd; + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true}; + WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = true, + .hostReqDelay = 500 };/*500 ms delay*/ + + if (ar->arWowState!= WLAN_WOW_STATE_NONE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); + return; + } + + ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ + +#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ + if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) { + } +#endif + +#if WOW_SET_SCAN_PARAMS + status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); +#endif + /* clear up our WoW pattern first */ + delWowCmd.filter_list_id = WOW_LIST_ID; + delWowCmd.filter_id = 0; + wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); + + /* setup unicast packet pattern for WoW */ + if (ar->arNetDev->dev_addr[1]) { + addWowCmd.filter_list_id = WOW_LIST_ID; + addWowCmd.filter_size = 6; /* MAC address */ + addWowCmd.filter_offset = 0; + status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); + } + } + /* setup ARP request for our own IP */ + if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { + if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { + break; /* found */ + } + } + } + if (ifa && ifa->ifa_local) { + WMI_SET_IP_CMD ipCmd; + memset(&ipCmd, 0, sizeof(ipCmd)); + ipCmd.ips[0] = ifa->ifa_local; + status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); + } + } + +#ifndef ATH6K_CONFIG_OTA_MODE + wmi_powermode_cmd(ar->arWmi, REC_POWER); +#endif + + status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); + } + ar6k_send_asleep_event_to_app(ar, true); + + status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); + } + + ar->arWowState = WLAN_WOW_STATE_SUSPENDING; + if (ar->arTxPending[ar->arControlEp]) { + u32 timeleft = wait_event_interruptible_timeout(arEvent, + ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); + if (!timeleft || signal_pending(current)) { + /* what can I do? wow resume at once */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); + } + } + + status = hifWaitForPendingRecv(ar->arHifDevice); + + ar->arWowState = WLAN_WOW_STATE_SUSPENDED; + ar->arWlanPowerState = WLAN_POWER_STATE_WOW; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); + } +} + +int ar6000_suspend_ev(void *context) +{ + int status = 0; + struct ar6_softc *ar = (struct ar6_softc *)context; + s16 pmmode = ar->arSuspendConfig; +wow_not_connected: + switch (pmmode) { + case WLAN_SUSPEND_WOW: + if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) { + ar6000_wow_suspend(ar); + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for wow mode %d\n", __func__, ar->arWlanPowerState)); + } else { + pmmode = ar->arWow2Config; + goto wow_not_connected; + } + break; + case WLAN_SUSPEND_CUT_PWR: + /* fall through */ + case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF: + /* fall through */ + case WLAN_SUSPEND_DEEP_SLEEP: + /* fall through */ + default: + status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true); + if (ar->arWlanPowerState==WLAN_POWER_STATE_ON || + ar->arWlanPowerState==WLAN_POWER_STATE_WOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status)); + status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY; + break; + } + + ar->scan_triggered = 0; + return status; +} + +int ar6000_resume_ev(void *context) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + u16 powerState = ar->arWlanPowerState; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState)); + switch (powerState) { + case WLAN_POWER_STATE_WOW: + ar6000_wow_resume(ar); + break; + case WLAN_POWER_STATE_CUT_PWR: + /* fall through */ + case WLAN_POWER_STATE_DEEP_SLEEP: + ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true); + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState)); + break; + case WLAN_POWER_STATE_ON: + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n")); + break; + } + return 0; +} + +void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent) +{ + if (ar->arWowState!=WLAN_WOW_STATE_NONE) { + if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__)); + return; + } + /* Wow resume from irq interrupt */ + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState)); + ar6000_wow_resume(ar); + } +} + +int ar6000_power_change_ev(void *context, u32 config) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config)); + switch (config) { + case HIF_DEVICE_POWER_UP: + ar6000_restart_endpoint(ar->arNetDev); + status = 0; + break; + case HIF_DEVICE_POWER_DOWN: + case HIF_DEVICE_POWER_CUT: + status = 0; + break; + } + return status; +} + +#endif /* CONFIG_PM */ + +int +ar6000_setup_cut_power_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status = 0; + HIF_DEVICE_POWER_CHANGE_TYPE config; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState)); +#ifdef CONFIG_PM + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); +#endif + do { + if (state == WLAN_ENABLED) { + /* Not in cut power state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { + break; + } + + /* Change the state to ON */ + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + + + /* Indicate POWER_UP to HIF */ + config = HIF_DEVICE_POWER_UP; + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + + if (status == A_PENDING) { + } else if (status == 0) { + ar6000_restart_endpoint(ar->arNetDev); + status = 0; + } + } else if (state == WLAN_DISABLED) { + + + /* Already in cut power state.. exit */ + if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { + break; + } + ar6000_stop_endpoint(ar->arNetDev, true, false); + + config = HIF_DEVICE_POWER_CUT; + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + + ar->arWlanPowerState = WLAN_POWER_STATE_CUT_PWR; + } + } while (0); + + return status; +} + +int +ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState)); +#ifdef CONFIG_PM + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); +#endif + do { + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode; + + if (state == WLAN_ENABLED) { + u16 fg_start_period; + + /* Not in deep sleep state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { + if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we resume from deep sleep %d\n", ar->arWlanPowerState)); + } + break; + } + + fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; + hostSleepMode.awake = true; + hostSleepMode.asleep = false; + + if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) { + break; + } + + /* Change the state to ON */ + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + + /* Enable foreground scanning */ + if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period, + ar->scParams.fg_end_period, + ar->scParams.bg_period, + ar->scParams.minact_chdwell_time, + ar->scParams.maxact_chdwell_time, + ar->scParams.pas_chdwell_time, + ar->scParams.shortScanRatio, + ar->scParams.scanCtrlFlags, + ar->scParams.max_dfsch_act_time, + ar->scParams.maxact_scan_per_ssid)) != 0) + { + break; + } + + if (ar->arNetworkType != AP_NETWORK) + { + if (ar->arSsidLen) { + if (ar6000_connect_to_ap(ar) != 0) { + /* no need to report error if connection failed */ + break; + } + } + } + } else if (state == WLAN_DISABLED){ + WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false }; + + /* Already in deep sleep state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { + if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we suspend for deep sleep %d\n", ar->arWlanPowerState)); + } + break; + } + + if (ar->arNetworkType != AP_NETWORK) + { + /* Disconnect from the AP and disable foreground scanning */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + if (ar->arConnected == true || ar->arConnectPending == true) { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + wmi_disconnect_cmd(ar->arWmi); + } else { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + } + } + + ar->scan_triggered = 0; + + if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) { + break; + } + + /* make sure we disable wow for deep sleep */ + if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0) + { + break; + } + + ar6000_TxDataCleanup(ar); +#ifndef ATH6K_CONFIG_OTA_MODE + wmi_powermode_cmd(ar->arWmi, REC_POWER); +#endif + + hostSleepMode.awake = false; + hostSleepMode.asleep = true; + if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) { + break; + } + if (ar->arTxPending[ar->arControlEp]) { + u32 timeleft = wait_event_interruptible_timeout(arEvent, + ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); + if (!timeleft || signal_pending(current)) { + status = A_ERROR; + break; + } + } + status = hifWaitForPendingRecv(ar->arHifDevice); + + ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP; + } + } while (0); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state)); + } + + return status; +} + +int +ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent) +{ + int status = 0; + u16 powerState, oldPowerState; + AR6000_WLAN_STATE oldstate = ar->arWlanState; + bool wlanOff = ar->arWlanOff; +#ifdef CONFIG_PM + bool btOff = ar->arBTOff; +#endif /* CONFIG_PM */ + + if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) { + return A_ERROR; + } + + if (ar->bIsDestroyProgress) { + return A_EBUSY; + } + + if (down_interruptible(&ar->arSem)) { + return A_ERROR; + } + + if (ar->bIsDestroyProgress) { + up(&ar->arSem); + return A_EBUSY; + } + + ar->arWlanState = wlanOff ? WLAN_DISABLED : state; + oldPowerState = ar->arWlanPowerState; + if (state == WLAN_ENABLED) { + powerState = ar->arWlanPowerState; + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to ENABLE^^\n")); + if (!wlanOff) { + if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { + status = ar6000_setup_deep_sleep_state(ar, WLAN_ENABLED); + } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { + status = ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + } + } +#ifdef CONFIG_PM + else if (pmEvent && wlanOff) { + bool allowCutPwr = ((!ar->arBTSharing) || btOff); + if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) { + /* Come out of cut power */ + ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); + } + } +#endif /* CONFIG_PM */ + } else if (state == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to DISABLED~\n")); + powerState = WLAN_POWER_STATE_DEEP_SLEEP; +#ifdef CONFIG_PM + if (pmEvent) { /* disable due to suspend */ + bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR || + (ar->arSuspendConfig == WLAN_SUSPEND_WOW && + ar->arWow2Config==WLAN_SUSPEND_CUT_PWR)); + bool suspendCutIfBtOff = ((ar->arSuspendConfig == + WLAN_SUSPEND_CUT_PWR_IF_BT_OFF || + (ar->arSuspendConfig == WLAN_SUSPEND_WOW && + ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) && + (!ar->arBTSharing || btOff)); + if ((suspendCutPwr) || + (suspendCutIfBtOff) || + (ar->arWlanState==WLAN_POWER_STATE_CUT_PWR)) + { + powerState = WLAN_POWER_STATE_CUT_PWR; + } + } else { + if ((wlanOff) && + (ar->arWlanOffConfig == WLAN_OFF_CUT_PWR) && + (!ar->arBTSharing || btOff)) + { + /* For BT clock sharing designs, CUT_POWER depend on BT state */ + powerState = WLAN_POWER_STATE_CUT_PWR; + } + } +#endif /* CONFIG_PM */ + + if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { + if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Load firmware before set to deep sleep\n")); + ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + } + status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); + } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { + status = ar6000_setup_cut_power_state(ar, WLAN_DISABLED); + } + + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState)); + ar->arWlanState = oldstate; + } else if (status == 0) { + WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent, *pSleepEvent = NULL; + if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) { + wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE; + pSleepEvent = &wmiSleepEvent; + } else if ((ar->arWlanPowerState != WLAN_POWER_STATE_ON) && (oldPowerState == WLAN_POWER_STATE_ON)) { + wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP; + pSleepEvent = &wmiSleepEvent; + } + if (pSleepEvent) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState)); + } + } + up(&ar->arSem); + return status; +} + +int +ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable) +{ +#ifdef CONFIG_PM + bool off = (enable == 0); + int status; + if (ar->arBTOff == off) { + return 0; + } + ar->arBTOff = off; + status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false); + return status; +#else + return 0; +#endif +} + +int +ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status; + bool off = (state == WLAN_DISABLED); + if (ar->arWlanOff == off) { + return 0; + } + ar->arWlanOff = off; + status = ar6000_update_wlan_pwr_state(ar, state, false); + return status; +} diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c new file mode 100644 index 000000000000..ae7c1dd96d83 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c @@ -0,0 +1,455 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#include "ar6000_drv.h" + +#ifdef HTC_RAW_INTERFACE + +static void +ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + raw_htc_buffer *busy; + HTC_RAW_STREAM_ID streamID; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + busy = (raw_htc_buffer *)pPacket->pPktContext; + A_ASSERT(busy != NULL); + + if (pPacket->Status == A_ECANCELED) { + /* + * HTC provides A_ECANCELED status when it doesn't want to be refilled + * (probably due to a shutdown) + */ + return; + } + + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); + +#ifdef CF + if (down_trylock(&arRaw->raw_htc_read_sem[streamID])) { +#else + if (down_interruptible(&arRaw->raw_htc_read_sem[streamID])) { +#endif /* CF */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); + } + + A_ASSERT((pPacket->Status != 0) || + (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN))); + + busy->length = pPacket->ActualLength + HTC_HEADER_LEN; + busy->currPtr = HTC_HEADER_LEN; + arRaw->read_buffer_available[streamID] = true; + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length); + up(&arRaw->raw_htc_read_sem[streamID]); + + /* Signal the waiting process */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) read process\n", streamID)); + wake_up_interruptible(&arRaw->raw_htc_read_queue[streamID]); +} + +static void +ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + raw_htc_buffer *free; + HTC_RAW_STREAM_ID streamID; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + free = (raw_htc_buffer *)pPacket->pPktContext; + A_ASSERT(free != NULL); + + if (pPacket->Status == A_ECANCELED) { + /* + * HTC provides A_ECANCELED status when it doesn't want to be refilled + * (probably due to a shutdown) + */ + return; + } + + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); + +#ifdef CF + if (down_trylock(&arRaw->raw_htc_write_sem[streamID])) { +#else + if (down_interruptible(&arRaw->raw_htc_write_sem[streamID])) { +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); + } + + A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN)); + + free->length = 0; + arRaw->write_buffer_available[streamID] = true; + up(&arRaw->raw_htc_write_sem[streamID]); + + /* Signal the waiting process */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) write process\n", streamID)); + wake_up_interruptible(&arRaw->raw_htc_write_queue[streamID]); +} + +/* connect to a service */ +static int ar6000_connect_raw_service(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID) +{ + int status; + struct htc_service_connect_resp response; + u8 streamNo; + struct htc_service_connect_req connect; + + do { + + A_MEMZERO(&connect,sizeof(connect)); + /* pass the stream ID as meta data to the RAW streams service */ + streamNo = (u8)StreamID; + connect.pMetaData = &streamNo; + connect.MetaDataLength = sizeof(u8); + /* these fields are the same for all endpoints */ + connect.EpCallbacks.pContext = ar; + connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb; + connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb; + /* simple interface, we don't need these optional callbacks */ + connect.EpCallbacks.EpRecvRefill = NULL; + connect.EpCallbacks.EpSendFull = NULL; + connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM; + + /* connect to the raw streams service, we may be able to get 1 or more + * connections, depending on WHAT is running on the target */ + connect.ServiceID = HTC_RAW_STREAMS_SVC; + + A_MEMZERO(&response,sizeof(response)); + + /* try to connect to the raw stream, it is okay if this fails with + * status HTC_SERVICE_NO_MORE_EP */ + status = HTCConnectService(ar->arHtcTarget, + &connect, + &response); + + if (status) { + if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n")); + status = 0; + } + break; + } + + /* set endpoint mapping for the RAW HTC streams */ + arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", + StreamID, arRawStream2EndpointID(ar,StreamID))); + + } while (false); + + return status; +} + +int ar6000_htc_raw_open(struct ar6_softc *ar) +{ + int status; + int streamID, endPt, count2; + raw_htc_buffer *buffer; + HTC_SERVICE_ID servicepriority; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + if (!arRaw) { + arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T)); + if (arRaw) { + A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T)); + } + } + A_ASSERT(ar->arHtcTarget != NULL); + if (!arRaw) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n")); + return -ENOMEM; + } + /* wait for target */ + status = HTCWaitTarget(ar->arHtcTarget); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status)); + return -ENODEV; + } + + for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) { + arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED; + } + + for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) { + /* Initialize the data structures */ + sema_init(&arRaw->raw_htc_read_sem[streamID], 1); + sema_init(&arRaw->raw_htc_write_sem[streamID], 1); + init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]); + init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]); + + /* try to connect to the raw service */ + status = ar6000_connect_raw_service(ar,streamID); + + if (status) { + break; + } + + if (arRawStream2EndpointID(ar,streamID) == 0) { + break; + } + + for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) { + /* Initialize the receive buffers */ + buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + buffer = &arRaw->raw_htc_read_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + + SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket, + buffer, + buffer->data, + HTC_RAW_BUFFER_SIZE, + arRawStream2EndpointID(ar,streamID)); + + /* Queue buffers to HTC for receive */ + if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0) + { + BMIInit(); + return -EIO; + } + } + + for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) { + /* Initialize the receive buffers */ + buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + } + + arRaw->read_buffer_available[streamID] = false; + arRaw->write_buffer_available[streamID] = true; + } + + if (status) { + return -EIO; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID)); + + servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */ + + /* set callbacks and priority list */ + HTCSetCreditDistribution(ar->arHtcTarget, + ar, + NULL, /* use default */ + NULL, /* use default */ + &servicepriority, + 1); + + /* Start the HTC component */ + if ((status = HTCStart(ar->arHtcTarget)) != 0) { + BMIInit(); + return -EIO; + } + + (ar)->arRawIfInit = true; + + return 0; +} + +int ar6000_htc_raw_close(struct ar6_softc *ar) +{ + A_PRINTF("ar6000_htc_raw_close called \n"); + HTCStop(ar->arHtcTarget); + + /* reset the device */ + ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false); + /* Initialize the BMI component */ + BMIInit(); + + return 0; +} + +raw_htc_buffer * +get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID) +{ + int count; + raw_htc_buffer *busy; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + /* Check for data */ + for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) { + busy = &arRaw->raw_htc_read_buffer[StreamID][count]; + if (busy->length) { + break; + } + } + if (busy->length) { + arRaw->read_buffer_available[StreamID] = true; + } else { + arRaw->read_buffer_available[StreamID] = false; + } + + return busy; +} + +ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t length) +{ + int readPtr; + raw_htc_buffer *busy; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + if (arRawStream2EndpointID(ar,StreamID) == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); + return -EFAULT; + } + + if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { + return -ERESTARTSYS; + } + + busy = get_filled_buffer(ar,StreamID); + while (!arRaw->read_buffer_available[StreamID]) { + up(&arRaw->raw_htc_read_sem[StreamID]); + + /* Wait for the data */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) read process\n", StreamID)); + if (wait_event_interruptible(arRaw->raw_htc_read_queue[StreamID], + arRaw->read_buffer_available[StreamID])) + { + return -EINTR; + } + if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { + return -ERESTARTSYS; + } + busy = get_filled_buffer(ar,StreamID); + } + + /* Read the data */ + readPtr = busy->currPtr; + if (length > busy->length - HTC_HEADER_LEN) { + length = busy->length - HTC_HEADER_LEN; + } + if (copy_to_user(buffer, &busy->data[readPtr], length)) { + up(&arRaw->raw_htc_read_sem[StreamID]); + return -EFAULT; + } + + busy->currPtr += length; + + if (busy->currPtr == busy->length) + { + busy->currPtr = 0; + busy->length = 0; + HTC_PACKET_RESET_RX(&busy->HTCPacket); + //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint)); + HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket); + } + arRaw->read_buffer_available[StreamID] = false; + up(&arRaw->raw_htc_read_sem[StreamID]); + + return length; +} + +static raw_htc_buffer * +get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID) +{ + int count; + raw_htc_buffer *free; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + free = NULL; + for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) { + free = &arRaw->raw_htc_write_buffer[StreamID][count]; + if (free->length == 0) { + break; + } + } + if (!free->length) { + arRaw->write_buffer_available[StreamID] = true; + } else { + arRaw->write_buffer_available[StreamID] = false; + } + + return free; +} + +ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t length) +{ + int writePtr; + raw_htc_buffer *free; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + if (arRawStream2EndpointID(ar,StreamID) == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); + return -EFAULT; + } + + if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { + return -ERESTARTSYS; + } + + /* Search for a free buffer */ + free = get_free_buffer(ar,StreamID); + + /* Check if there is space to write else wait */ + while (!arRaw->write_buffer_available[StreamID]) { + up(&arRaw->raw_htc_write_sem[StreamID]); + + /* Wait for buffer to become free */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID)); + if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID], + arRaw->write_buffer_available[StreamID])) + { + return -EINTR; + } + if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { + return -ERESTARTSYS; + } + free = get_free_buffer(ar,StreamID); + } + + /* Send the data */ + writePtr = HTC_HEADER_LEN; + if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) { + length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN; + } + + if (copy_from_user(&free->data[writePtr], buffer, length)) { + up(&arRaw->raw_htc_read_sem[StreamID]); + return -EFAULT; + } + + free->length = length; + + SET_HTC_PACKET_INFO_TX(&free->HTCPacket, + free, + &free->data[writePtr], + length, + arRawStream2EndpointID(ar,StreamID), + AR6K_DATA_PKT_TAG); + + HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); + + arRaw->write_buffer_available[StreamID] = false; + up(&arRaw->raw_htc_write_sem[StreamID]); + + return length; +} +#endif /* HTC_RAW_INTERFACE */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c b/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c new file mode 100644 index 000000000000..5fdda4aa2fee --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c @@ -0,0 +1,1892 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +#include "ar6000_drv.h" + + +extern A_WAITQUEUE_HEAD arEvent; +extern unsigned int wmitimeout; +extern int reconnect_flag; + + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .flags = (_flags), \ + .hw_value = (_rateid), \ +} + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = 5000 + (5 * (_channel)), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct +ieee80211_rate ar6k_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#define ar6k_a_rates (ar6k_rates + 4) +#define ar6k_a_rates_size 8 +#define ar6k_g_rates (ar6k_rates + 0) +#define ar6k_g_rates_size 12 + +static struct +ieee80211_channel ar6k_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct +ieee80211_channel ar6k_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct +ieee80211_supported_band ar6k_band_2ghz = { + .n_channels = ARRAY_SIZE(ar6k_2ghz_channels), + .channels = ar6k_2ghz_channels, + .n_bitrates = ar6k_g_rates_size, + .bitrates = ar6k_g_rates, +}; + +static struct +ieee80211_supported_band ar6k_band_5ghz = { + .n_channels = ARRAY_SIZE(ar6k_5ghz_a_channels), + .channels = ar6k_5ghz_a_channels, + .n_bitrates = ar6k_a_rates_size, + .bitrates = ar6k_a_rates, +}; + +static int +ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version)); + + if (!wpa_version) { + ar->arAuthMode = NONE_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_1) { + ar->arAuthMode = WPA_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_2) { + ar->arAuthMode = WPA2_AUTH; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: %u not spported\n", __func__, wpa_version)); + return -ENOTSUPP; + } + + return 0; +} + +static int +ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type)); + + switch (auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + ar->arDot11AuthMode = OPEN_AUTH; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + ar->arDot11AuthMode = SHARED_AUTH; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + ar->arDot11AuthMode = LEAP_AUTH; + break; + + case NL80211_AUTHTYPE_AUTOMATIC: + ar->arDot11AuthMode = OPEN_AUTH; + ar->arAutoAuthStage = AUTH_OPEN_IN_PROGRESS; + break; + + default: + ar->arDot11AuthMode = OPEN_AUTH; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: 0x%x not spported\n", __func__, auth_type)); + return -ENOTSUPP; + } + + return 0; +} + +static int +ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast) +{ + u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto : + &ar->arGroupCrypto; + u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen : + &ar->arGroupCryptoLen; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: cipher 0x%x, ucast %u\n", __func__, cipher, ucast)); + + switch (cipher) { + case 0: + case IW_AUTH_CIPHER_NONE: + *ar_cipher = NONE_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_WEP40: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 5; + break; + case WLAN_CIPHER_SUITE_WEP104: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 13; + break; + case WLAN_CIPHER_SUITE_TKIP: + *ar_cipher = TKIP_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_CCMP: + *ar_cipher = AES_CRYPT; + *ar_cipher_len = 0; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: cipher 0x%x not supported\n", __func__, cipher)); + return -ENOTSUPP; + } + + return 0; +} + +static void +ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt)); + + if (WLAN_AKM_SUITE_PSK == key_mgmt) { + if (WPA_AUTH == ar->arAuthMode) { + ar->arAuthMode = WPA_PSK_AUTH; + } else if (WPA2_AUTH == ar->arAuthMode) { + ar->arAuthMode = WPA2_PSK_AUTH; + } + } else if (WLAN_AKM_SUITE_8021X != key_mgmt) { + ar->arAuthMode = NONE_AUTH; + } +} + +static int +ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct ar6_softc *ar = ar6k_priv(dev); + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + ar->smeState = SME_CONNECTING; + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: destroy in progress\n", __func__)); + return -EBUSY; + } + + if(!sme->ssid_len || IEEE80211_MAX_SSID_LEN < sme->ssid_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); + return -EINVAL; + } + + if(ar->arSkipScan == true && + ((sme->channel && sme->channel->center_freq == 0) || + (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] && + !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5]))) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s:SkipScan: channel or bssid invalid\n", __func__)); + return -EINVAL; + } + + if(down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return -ERESTARTSYS; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); + up(&ar->arSem); + return -EBUSY; + } + + if(ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) { + /* + * sleep until the command queue drains + */ + wait_event_interruptible_timeout(arEvent, + ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ); + if (signal_pending(current)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: cmd queue drain timeout\n", __func__)); + up(&ar->arSem); + return -EINTR; + } + } + + if(ar->arConnected == true && + ar->arSsidLen == sme->ssid_len && + !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { + reconnect_flag = true; + status = wmi_reconnect_cmd(ar->arWmi, + ar->arReqBssid, + ar->arChannelHint); + + up(&ar->arSem); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__)); + return -EIO; + } + return 0; + } else if(ar->arSsidLen == sme->ssid_len && + !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { + ar6000_disconnect(ar); + } + + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = sme->ssid_len; + memcpy(ar->arSsid, sme->ssid, sme->ssid_len); + + if(sme->channel){ + ar->arChannelHint = sme->channel->center_freq; + } + + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + if(sme->bssid){ + if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { + memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid)); + } + } + + ar6k_set_wpa_version(ar, sme->crypto.wpa_versions); + ar6k_set_auth_type(ar, sme->auth_type); + + if(sme->crypto.n_ciphers_pairwise) { + ar6k_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true); + } else { + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); + } + ar6k_set_cipher(ar, sme->crypto.cipher_group, false); + + if(sme->crypto.n_akm_suites) { + ar6k_set_key_mgmt(ar, sme->crypto.akm_suites[0]); + } + + if((sme->key_len) && + (NONE_AUTH == ar->arAuthMode) && + (WEP_CRYPT == ar->arPairwiseCrypto)) { + struct ar_key *key = NULL; + + if(sme->key_idx < WMI_MIN_KEY_INDEX || sme->key_idx > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: key index %d out of bounds\n", __func__, sme->key_idx)); + up(&ar->arSem); + return -ENOENT; + } + + key = &ar->keys[sme->key_idx]; + key->key_len = sme->key_len; + memcpy(key->key, sme->key, key->key_len); + key->cipher = ar->arPairwiseCrypto; + ar->arDefTxKeyIndex = sme->key_idx; + + wmi_addKey_cmd(ar->arWmi, sme->key_idx, + ar->arPairwiseCrypto, + GROUP_USAGE | TX_USAGE, + key->key_len, + NULL, + key->key, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); + up(&ar->arSem); + return -EIO; + } + } + + ar->arNetworkType = ar->arNextMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d channel hint %u\n", + __func__, ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); + + reconnect_flag = 0; + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + + up(&ar->arSem); + + if (A_EINVAL == status) { + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__)); + return -ENOENT; + } else if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__)); + return -EIO; + } + + if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && + ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) + { + A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); + } + + ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; + ar->arConnectPending = true; + + return 0; +} + +void +ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval,NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen, u8 *assocInfo) +{ + u16 size = 0; + u16 capability = 0; + struct cfg80211_bss *bss = NULL; + struct ieee80211_mgmt *mgmt = NULL; + struct ieee80211_channel *ibss_channel = NULL; + s32 signal = 50 * 100; + u8 ie_buf_len = 0; + unsigned char ie_buf[256]; + unsigned char *ptr_ie_buf = ie_buf; + unsigned char *ieeemgmtbuf = NULL; + u8 source_mac[ATH_MAC_LEN]; + + u8 assocReqIeOffset = sizeof(u16) + /* capinfo*/ + sizeof(u16); /* listen interval */ + u8 assocRespIeOffset = sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16); /* associd */ + u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset; + u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + assocReqLen -= assocReqIeOffset; + assocRespLen -= assocRespIeOffset; + + ar->arAutoAuthStage = AUTH_IDLE; + + if((ADHOC_NETWORK & networkType)) { + if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in ibss mode\n", __func__)); + return; + } + } + + if((INFRA_NETWORK & networkType)) { + if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in station mode\n", __func__)); + return; + } + } + + /* Before informing the join/connect event, make sure that + * bss entry is present in scan list, if it not present + * construct and insert into scan list, otherwise that + * event will be dropped on the way by cfg80211, due to + * this keys will not be plumbed in case of WEP and + * application will not be aware of join/connect status. */ + bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, + ar->wdev->ssid, ar->wdev->ssid_len, + ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS), + ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS)); + + /* + * Earlier we were updating the cfg about bss by making a beacon frame + * only if the entry for bss is not there. This can have some issue if + * ROAM event is generated and a heavy traffic is ongoing. The ROAM + * event is handled through a work queue and by the time it really gets + * handled, BSS would have been aged out. So it is better to update the + * cfg about BSS irrespective of its entry being present right now or + * not. + */ + + if (ADHOC_NETWORK & networkType) { + /* construct 802.11 mgmt beacon */ + if(ptr_ie_buf) { + *ptr_ie_buf++ = WLAN_EID_SSID; + *ptr_ie_buf++ = ar->arSsidLen; + memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen); + ptr_ie_buf +=ar->arSsidLen; + + *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; + *ptr_ie_buf++ = 2; /* length */ + *ptr_ie_buf++ = 0; /* ATIM window */ + *ptr_ie_buf++ = 0; /* ATIM window */ + + /* TODO: update ibss params and include supported rates, + * DS param set, extened support rates, wmm. */ + + ie_buf_len = ptr_ie_buf - ie_buf; + } + + capability |= IEEE80211_CAPINFO_IBSS; + if(WEP_CRYPT == ar->arPairwiseCrypto) { + capability |= IEEE80211_CAPINFO_PRIVACY; + } + memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN); + ptr_ie_buf = ie_buf; + } else { + capability = *(u16 *)(&assocInfo[beaconIeLen]); + memcpy(source_mac, bssid, ATH_MAC_LEN); + ptr_ie_buf = assocReqIe; + ie_buf_len = assocReqLen; + } + + size = offsetof(struct ieee80211_mgmt, u) + + sizeof(mgmt->u.beacon) + + ie_buf_len; + + ieeemgmtbuf = A_MALLOC_NOWAIT(size); + if(!ieeemgmtbuf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: ieeeMgmtbuf alloc error\n", __func__)); + cfg80211_put_bss(bss); + return; + } + + A_MEMZERO(ieeemgmtbuf, size); + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); + memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); + memcpy(mgmt->sa, source_mac, ATH_MAC_LEN); + memcpy(mgmt->bssid, bssid, ATH_MAC_LEN); + mgmt->u.beacon.beacon_int = beaconInterval; + mgmt->u.beacon.capab_info = capability; + memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); + + ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: inform bss with bssid %pM channel %d beaconInterval %d " + "capability 0x%x\n", __func__, mgmt->bssid, + ibss_channel->hw_value, beaconInterval, capability)); + + bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, + ibss_channel, mgmt, + le16_to_cpu(size), + signal, GFP_KERNEL); + kfree(ieeemgmtbuf); + cfg80211_put_bss(bss); + + if((ADHOC_NETWORK & networkType)) { + cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); + return; + } + + if (false == ar->arConnected) { + /* inform connect result to cfg80211 */ + ar->smeState = SME_DISCONNECTED; + cfg80211_connect_result(ar->arNetDev, bssid, + assocReqIe, assocReqLen, + assocRespIe, assocRespLen, + WLAN_STATUS_SUCCESS, GFP_KERNEL); + } else { + /* inform roam event to cfg80211 */ + cfg80211_roamed(ar->arNetDev, ibss_channel, bssid, + assocReqIe, assocReqLen, + assocRespIe, assocRespLen, + GFP_KERNEL); + } +} + +static int +ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); + return -EBUSY; + } + + if(down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return -ERESTARTSYS; + } + + reconnect_flag = 0; + ar6000_disconnect(ar); + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + + if (ar->arSkipScan == false) { + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + } + + up(&ar->arSem); + + return 0; +} + +void +ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus) +{ + + u16 status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason)); + + if (ar->scan_request) { + cfg80211_scan_done(ar->scan_request, true); + ar->scan_request = NULL; + } + if((ADHOC_NETWORK & ar->arNetworkType)) { + if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in ibss mode\n", __func__)); + return; + } + A_MEMZERO(bssid, ETH_ALEN); + cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); + return; + } + + if((INFRA_NETWORK & ar->arNetworkType)) { + if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in station mode\n", __func__)); + return; + } + } + + if(true == ar->arConnectPending) { + if(NO_NETWORK_AVAIL == reason) { + /* connect cmd failed */ + wmi_disconnect_cmd(ar->arWmi); + } else if (reason == DISCONNECT_CMD) { + if (ar->arAutoAuthStage) { + /* + * If the current auth algorithm is open try shared + * and make autoAuthStage idle. We do not make it + * leap for now being. + */ + if (ar->arDot11AuthMode == OPEN_AUTH) { + struct ar_key *key = NULL; + key = &ar->keys[ar->arDefTxKeyIndex]; + if (down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return; + } + + + ar->arDot11AuthMode = SHARED_AUTH; + ar->arAutoAuthStage = AUTH_IDLE; + + wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, + ar->arPairwiseCrypto, + GROUP_USAGE | TX_USAGE, + key->key_len, + NULL, + key->key, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + + status = wmi_connect_cmd(ar->arWmi, + ar->arNetworkType, + ar->arDot11AuthMode, + ar->arAuthMode, + ar->arPairwiseCrypto, + ar->arPairwiseCryptoLen, + ar->arGroupCrypto, + ar->arGroupCryptoLen, + ar->arSsidLen, + ar->arSsid, + ar->arReqBssid, + ar->arChannelHint, + ar->arConnectCtrlFlags); + up(&ar->arSem); + + } else if (ar->arDot11AuthMode == SHARED_AUTH) { + /* should not reach here */ + } + } else { + ar->arConnectPending = false; + if (ar->smeState == SME_CONNECTING) { + cfg80211_connect_result(ar->arNetDev, bssid, + NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else { + cfg80211_disconnected(ar->arNetDev, + reason, + NULL, 0, + GFP_KERNEL); + } + ar->smeState = SME_DISCONNECTED; + } + } + } else { + if (reason != DISCONNECT_CMD) + wmi_disconnect_cmd(ar->arWmi); + } +} + +void +ar6k_cfg80211_scan_node(void *arg, bss_t *ni) +{ + struct wiphy *wiphy = (struct wiphy *)arg; + u16 size; + unsigned char *ieeemgmtbuf = NULL; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct ieee80211_common_ie *cie; + s32 signal; + int freq; + + cie = &ni->ni_cie; + +#define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484))) + if(CHAN_IS_11A(cie->ie_chan)) { + /* 11a */ + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + } else if((cie->ie_erp) || (cie->ie_xrates)) { + /* 11g */ + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + } else { + /* 11b */ + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + } + + size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); + ieeemgmtbuf = A_MALLOC_NOWAIT(size); + if(!ieeemgmtbuf) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ieeeMgmtbuf alloc error\n", __func__)); + return; + } + + /* Note: + TODO: Update target to include 802.11 mac header while sending bss info. + Target removes 802.11 mac header while sending the bss info to host, + cfg80211 needs it, for time being just filling the da, sa and bssid fields alone. + */ + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); + memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN); + memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN); + memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), + ni->ni_buf, ni->ni_framelen); + + freq = cie->ie_chan; + channel = ieee80211_get_channel(wiphy, freq); + signal = ni->ni_snr * 100; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: bssid %pM channel %d freq %d size %d\n", __func__, + mgmt->bssid, channel->hw_value, freq, size)); + cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(size), + signal, GFP_KERNEL); + + kfree (ieeemgmtbuf); +} + +static int +ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + int ret = 0; + u32 forceFgScan = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, + (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), + 0) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); + return -EIO; + } + } + + if(request->n_ssids && + request->ssids[0].ssid_len) { + u8 i; + + if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) { + request->n_ssids = MAX_PROBED_SSID_INDEX - 1; + } + + for (i = 0; i < request->n_ssids; i++) { + wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG, + request->ssids[i].ssid_len, + request->ssids[i].ssid); + } + } + + if(ar->arConnected) { + forceFgScan = 1; + } + + if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \ + 0, 0, 0, NULL) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__)); + ret = -EIO; + } + + ar->scan_request = request; + + return ret; +} + +void +ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status)); + + if (!ar->scan_request) + return; + + if ((status == A_ECANCELED) || (status == A_EBUSY)) { + cfg80211_scan_done(ar->scan_request, true); + goto out; + } + + /* Translate data to cfg80211 mgmt format */ + wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); + + cfg80211_scan_done(ar->scan_request, false); + + if(ar->scan_request->n_ssids && + ar->scan_request->ssids[0].ssid_len) { + u8 i; + + for (i = 0; i < ar->scan_request->n_ssids; i++) { + wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, + 0, NULL); + } + } + +out: + ar->scan_request = NULL; +} + +static int +ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + u8 key_usage; + u8 key_type; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + key = &ar->keys[key_index]; + A_MEMZERO(key, sizeof(struct ar_key)); + + if(!mac_addr || is_broadcast_ether_addr(mac_addr)) { + key_usage = GROUP_USAGE; + } else { + key_usage = PAIRWISE_USAGE; + } + + if(params) { + if(params->key_len > WLAN_MAX_KEY_LEN || + params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) + return -EINVAL; + + key->key_len = params->key_len; + memcpy(key->key, params->key, key->key_len); + key->seq_len = params->seq_len; + memcpy(key->seq, params->seq, key->seq_len); + key->cipher = params->cipher; + } + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + key_type = WEP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_TKIP: + key_type = TKIP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_CCMP: + key_type = AES_CRYPT; + break; + + default: + return -ENOTSUPP; + } + + if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) && + (GROUP_USAGE & key_usage)) + { + A_UNTIMEOUT(&ar->disconnect_timer); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: index %d, key_len %d, key_type 0x%x,"\ + " key_usage 0x%x, seq_len %d\n", + __func__, key_index, key->key_len, key_type, + key_usage, key->seq_len)); + + ar->arDefTxKeyIndex = key_index; + status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage, + key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, + (u8 *)mac_addr, SYNC_BOTH_WMIFLAG); + + + if (status) { + return -EIO; + } + + return 0; +} + +static int +ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + if(!ar->keys[key_index].key_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d is empty\n", __func__, key_index)); + return 0; + } + + ar->keys[key_index].key_len = 0; + + return wmi_deleteKey_cmd(ar->arWmi, key_index); +} + + +static int +ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*)) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + struct key_params params; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + key = &ar->keys[key_index]; + A_MEMZERO(¶ms, sizeof(params)); + params.cipher = key->cipher; + params.key_len = key->key_len; + params.seq_len = key->seq_len; + params.seq = key->seq; + params.key = key->key; + + callback(cookie, ¶ms); + + return key->key_len ? 0 : -ENOENT; +} + + +static int +ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool unicast, bool multicast) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + int status = 0; + u8 key_usage; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", + __func__, key_index)); + return -ENOENT; + } + + if(!ar->keys[key_index].key_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: invalid key index %d\n", + __func__, key_index)); + return -EINVAL; + } + + ar->arDefTxKeyIndex = key_index; + key = &ar->keys[ar->arDefTxKeyIndex]; + key_usage = GROUP_USAGE; + if (WEP_CRYPT == ar->arPairwiseCrypto) { + key_usage |= TX_USAGE; + } + + status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, + ar->arPairwiseCrypto, key_usage, + key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, + NULL, SYNC_BOTH_WMIFLAG); + if (status) { + return -EIO; + } + + return 0; +} + +static int +ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + return -ENOTSUPP; +} + +void +ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast)); + + cfg80211_michael_mic_failure(ar->arNetDev, ar->arBssid, + (ismcast ? NL80211_KEYTYPE_GROUP : NL80211_KEYTYPE_PAIRWISE), + keyid, NULL, GFP_KERNEL); +} + +static int +ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__)); + return -EIO; + } + } + + return 0; +} + +static int +ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n")); + return -EIO; +} + +/* The type nl80211_tx_power_setting replaces the following data type from 2.6.36 onwards */ +static int +ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + u8 ar_dbm; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + ar->arTxPwrSet = false; + switch(type) { + case NL80211_TX_POWER_AUTOMATIC: + return 0; + case NL80211_TX_POWER_LIMITED: + ar->arTxPwr = ar_dbm = dbm; + ar->arTxPwrSet = true; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type)); + return -EOPNOTSUPP; + } + + wmi_set_txPwr_cmd(ar->arWmi, ar_dbm); + + return 0; +} + +static int +ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if((ar->arConnected == true)) { + ar->arTxPwr = 0; + + if(wmi_get_txPwr_cmd(ar->arWmi) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__)); + return -EIO; + } + + wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, 5 * HZ); + + if(signal_pending(current)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Target did not respond\n", __func__)); + return -EINTR; + } + } + + *dbm = ar->arTxPwr; + return 0; +} + +static int +ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool pmgmt, int timeout) +{ + struct ar6_softc *ar = ar6k_priv(dev); + WMI_POWER_MODE_CMD pwrMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(pmgmt) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Max Perf\n", __func__)); + pwrMode.powerMode = REC_POWER; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Rec Power\n", __func__)); + pwrMode.powerMode = MAX_PERF_POWER; + } + + if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__)); + return -EIO; + } + + return 0; +} + +static struct net_device * +ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + + /* Multiple virtual interface is not supported. + * The default interface supports STA and IBSS type + */ + return ERR_PTR(-EOPNOTSUPP); +} + +static int +ar6k_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + + /* Multiple virtual interface is not supported. + * The default interface supports STA and IBSS type + */ + return -EOPNOTSUPP; +} + +static int +ar6k_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct ar6_softc *ar = ar6k_priv(ndev); + struct wireless_dev *wdev = ar->wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + switch (type) { + case NL80211_IFTYPE_STATION: + ar->arNextMode = INFRA_NETWORK; + break; + case NL80211_IFTYPE_ADHOC: + ar->arNextMode = ADHOC_NETWORK; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: type %u\n", __func__, type)); + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + return 0; +} + +static int +ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *ibss_param) +{ + struct ar6_softc *ar = ar6k_priv(dev); + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(!ibss_param->ssid_len || IEEE80211_MAX_SSID_LEN < ibss_param->ssid_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); + return -EINVAL; + } + + ar->arSsidLen = ibss_param->ssid_len; + memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen); + + if(ibss_param->channel) { + ar->arChannelHint = ibss_param->channel->center_freq; + } + + if(ibss_param->channel_fixed) { + /* TODO: channel_fixed: The channel should be fixed, do not search for + * IBSSs to join on other channels. Target firmware does not support this + * feature, needs to be updated.*/ + } + + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + if(ibss_param->bssid) { + if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { + memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid)); + } + } + + ar6k_set_wpa_version(ar, 0); + ar6k_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM); + + if(ibss_param->privacy) { + ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true); + ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false); + } else { + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, false); + } + + ar->arNetworkType = ar->arNextMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d channel hint %u\n", + __func__, ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); + + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + ar->arConnectPending = true; + + return 0; +} + +static int +ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + ar6000_disconnect(ar); + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + + return 0; +} + +#ifdef CONFIG_NL80211_TESTMODE +enum ar6k_testmode_attr { + __AR6K_TM_ATTR_INVALID = 0, + AR6K_TM_ATTR_CMD = 1, + AR6K_TM_ATTR_DATA = 2, + + /* keep last */ + __AR6K_TM_ATTR_AFTER_LAST, + AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1 +}; + +enum ar6k_testmode_cmd { + AR6K_TM_CMD_TCMD = 0, + AR6K_TM_CMD_RX_REPORT = 1, +}; + +#define AR6K_TM_DATA_MAX_LEN 5000 + +static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = { + [AR6K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = AR6K_TM_DATA_MAX_LEN }, +}; + +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len) +{ + if (down_interruptible(&ar->arSem)) + return; + + kfree(ar->tcmd_rx_report); + + ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL); + ar->tcmd_rx_report_len = buf_len; + + up(&ar->arSem); + + wake_up(&arEvent); +} + +static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf, + int buf_len, struct sk_buff *skb) +{ + int ret = 0; + long left; + + if (down_interruptible(&ar->arSem)) + return -ERESTARTSYS; + + if (ar->arWmiReady == false) { + ret = -EIO; + goto out; + } + + if (ar->bIsDestroyProgress) { + ret = -EBUSY; + goto out; + } + + WARN_ON(ar->tcmd_rx_report != NULL); + WARN_ON(ar->tcmd_rx_report_len > 0); + + if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) { + up(&ar->arSem); + return -EIO; + } + + left = wait_event_interruptible_timeout(arEvent, + ar->tcmd_rx_report != NULL, + wmitimeout * HZ); + + if (left == 0) { + ret = -ETIMEDOUT; + goto out; + } else if (left < 0) { + ret = left; + goto out; + } + + if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) { + ret = -EINVAL; + goto out; + } + + NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len, + ar->tcmd_rx_report); + + kfree(ar->tcmd_rx_report); + ar->tcmd_rx_report = NULL; + +out: + up(&ar->arSem); + + return ret; + +nla_put_failure: + ret = -ENOBUFS; + goto out; +} + +static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct ar6_softc *ar = wiphy_priv(wiphy); + struct nlattr *tb[AR6K_TM_ATTR_MAX + 1]; + int err, buf_len, reply_len; + struct sk_buff *skb; + void *buf; + + err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len, + ar6k_testmode_policy); + if (err) + return err; + + if (!tb[AR6K_TM_ATTR_CMD]) + return -EINVAL; + + switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) { + case AR6K_TM_CMD_TCMD: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + wmi_test_cmd(ar->arWmi, buf, buf_len); + + return 0; + + break; + case AR6K_TM_CMD_RX_REPORT: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN); + skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); + if (!skb) + return -ENOMEM; + + err = ar6000_testmode_rx_report(ar, buf, buf_len, skb); + if (err < 0) { + kfree_skb(skb); + return err; + } + + return cfg80211_testmode_reply(skb); + default: + return -EOPNOTSUPP; + } +} +#endif + +static const +u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +bool is_rate_legacy(s32 rate) +{ + static const s32 legacy[] = { 1000, 2000, 5500, 11000, + 6000, 9000, 12000, 18000, 24000, + 36000, 48000, 54000 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(legacy); i++) { + if (rate == legacy[i]) + return true; + } + + return false; +} + +bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000, + 52000, 58500, 65000, 72200 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht20); i++) { + if (rate == ht20[i]) { + if (i == ARRAY_SIZE(ht20) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + return false; +} + +bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht40[] = { 13500, 27000, 40500, 54000, + 81000, 108000, 121500, 135000, + 150000 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht40); i++) { + if (rate == ht40[i]) { + if (i == ARRAY_SIZE(ht40) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + + return false; +} + +static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + struct ar6_softc *ar = ar6k_priv(dev); + long left; + bool sgi; + s32 rate; + int ret; + u8 mcs; + + if (memcmp(mac, ar->arBssid, ETH_ALEN) != 0) + return -ENOENT; + + if (down_interruptible(&ar->arSem)) + return -EBUSY; + + ar->statsUpdatePending = true; + + ret = wmi_get_stats_cmd(ar->arWmi); + + if (ret != 0) { + up(&ar->arSem); + return -EIO; + } + + left = wait_event_interruptible_timeout(arEvent, + ar->statsUpdatePending == false, + wmitimeout * HZ); + + up(&ar->arSem); + + if (left == 0) + return -ETIMEDOUT; + else if (left < 0) + return left; + + if (ar->arTargetStats.rx_bytes) { + sinfo->rx_bytes = ar->arTargetStats.rx_bytes; + sinfo->filled |= STATION_INFO_RX_BYTES; + sinfo->rx_packets = ar->arTargetStats.rx_packets; + sinfo->filled |= STATION_INFO_RX_PACKETS; + } + + if (ar->arTargetStats.tx_bytes) { + sinfo->tx_bytes = ar->arTargetStats.tx_bytes; + sinfo->filled |= STATION_INFO_TX_BYTES; + sinfo->tx_packets = ar->arTargetStats.tx_packets; + sinfo->filled |= STATION_INFO_TX_PACKETS; + } + + sinfo->signal = ar->arTargetStats.cs_rssi; + sinfo->filled |= STATION_INFO_SIGNAL; + + rate = ar->arTargetStats.tx_unicast_rate; + + if (is_rate_legacy(rate)) { + sinfo->txrate.legacy = rate / 100; + } else if (is_rate_ht20(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else if (is_rate_ht40(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else { + WARN(1, "invalid rate: %d", rate); + return 0; + } + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + return 0; +} + +static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true); +} + +static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false); +} + +static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + if (ar->arConnected) + return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false); + return 0; +} + +static struct +cfg80211_ops ar6k_cfg80211_ops = { + .change_virtual_intf = ar6k_cfg80211_change_iface, + .add_virtual_intf = ar6k_cfg80211_add_virtual_intf, + .del_virtual_intf = ar6k_cfg80211_del_virtual_intf, + .scan = ar6k_cfg80211_scan, + .connect = ar6k_cfg80211_connect, + .disconnect = ar6k_cfg80211_disconnect, + .add_key = ar6k_cfg80211_add_key, + .get_key = ar6k_cfg80211_get_key, + .del_key = ar6k_cfg80211_del_key, + .set_default_key = ar6k_cfg80211_set_default_key, + .set_default_mgmt_key = ar6k_cfg80211_set_default_mgmt_key, + .set_wiphy_params = ar6k_cfg80211_set_wiphy_params, + .set_bitrate_mask = ar6k_cfg80211_set_bitrate_mask, + .set_tx_power = ar6k_cfg80211_set_txpower, + .get_tx_power = ar6k_cfg80211_get_txpower, + .set_power_mgmt = ar6k_cfg80211_set_power_mgmt, + .join_ibss = ar6k_cfg80211_join_ibss, + .leave_ibss = ar6k_cfg80211_leave_ibss, + .get_station = ar6k_get_station, + .set_pmksa = ar6k_set_pmksa, + .del_pmksa = ar6k_del_pmksa, + .flush_pmksa = ar6k_flush_pmksa, + CFG80211_TESTMODE_CMD(ar6k_testmode_cmd) +}; + +struct wireless_dev * +ar6k_cfg80211_init(struct device *dev) +{ + int ret = 0; + struct wireless_dev *wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if(!wdev) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't allocate wireless device\n", __func__)); + return ERR_PTR(-ENOMEM); + } + + /* create a new wiphy for use with cfg80211 */ + wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc)); + if(!wdev->wiphy) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't allocate wiphy device\n", __func__)); + kfree(wdev); + return ERR_PTR(-ENOMEM); + } + + /* set device pointer for wiphy */ + set_wiphy_dev(wdev->wiphy, dev); + + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* max num of ssids that can be probed during scanning */ + wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar6k_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar6k_band_5ghz; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + ret = wiphy_register(wdev->wiphy); + if(ret < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't register wiphy device\n", __func__)); + wiphy_free(wdev->wiphy); + return ERR_PTR(ret); + } + + return wdev; +} + +void +ar6k_cfg80211_deinit(struct ar6_softc *ar) +{ + struct wireless_dev *wdev = ar->wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->scan_request) { + cfg80211_scan_done(ar->scan_request, true); + ar->scan_request = NULL; + } + + if(!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} + + + + + + + diff --git a/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c b/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c new file mode 100644 index 000000000000..430998edacc4 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c @@ -0,0 +1,124 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "a_drv.h" +#include "hif.h" +#include "common_drv.h" +#include "a_debug.h" +#include "hci_transport_api.h" + +#include "AR6002/hw4.0/hw/apb_athr_wlan_map.h" +#include "AR6002/hw4.0/hw/uart_reg.h" +#include "AR6002/hw4.0/hw/rtc_wlan_reg.h" + +HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); +void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); +int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); +void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); +int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); +int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); +int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +extern struct hci_transport_callbacks ar6kHciTransCallbacks; + +int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks) +{ + ar6kHciTransCallbacks = *hciTransCallbacks; + + _HCI_TransportAttach = HCI_TransportAttach; + _HCI_TransportDetach = HCI_TransportDetach; + _HCI_TransportAddReceivePkts = HCI_TransportAddReceivePkts; + _HCI_TransportSendPkt = HCI_TransportSendPkt; + _HCI_TransportStop = HCI_TransportStop; + _HCI_TransportStart = HCI_TransportStart; + _HCI_TransportEnableDisableAsyncRecv = HCI_TransportEnableDisableAsyncRecv; + _HCI_TransportRecvHCIEventSync = HCI_TransportRecvHCIEventSync; + _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate; + _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt; + + return 0; +} + +int +ar6000_get_hif_dev(struct hif_device *device, void *config) +{ + int status; + + status = HIFConfigureDevice(device, + HIF_DEVICE_GET_OS_DEVICE, + (struct hif_device_os_device_info *)config, + sizeof(struct hif_device_os_device_info)); + return status; +} + +int ar6000_set_uart_config(struct hif_device *hifDevice, + u32 scale, + u32 step) +{ + u32 regAddress; + u32 regVal; + int status; + + regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS; + regVal = ((u32)scale << 16) | step; + /* change the HCI UART scale/step values through the diagnostic window */ + status = ar6000_WriteRegDiag(hifDevice, ®Address, ®Val); + + return status; +} + +int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data) +{ + u32 regAddress; + int status; + + regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS; + /* read CPU clock settings*/ + status = ar6000_ReadRegDiag(hifDevice, ®Address, data); + + return status; +} + +EXPORT_SYMBOL(ar6000_register_hci_transport); +EXPORT_SYMBOL(ar6000_get_hif_dev); +EXPORT_SYMBOL(ar6000_set_uart_config); +EXPORT_SYMBOL(ar6000_get_core_clock_config); +EXPORT_SYMBOL(_HCI_TransportAttach); +EXPORT_SYMBOL(_HCI_TransportDetach); +EXPORT_SYMBOL(_HCI_TransportAddReceivePkts); +EXPORT_SYMBOL(_HCI_TransportSendPkt); +EXPORT_SYMBOL(_HCI_TransportStop); +EXPORT_SYMBOL(_HCI_TransportStart); +EXPORT_SYMBOL(_HCI_TransportEnableDisableAsyncRecv); +EXPORT_SYMBOL(_HCI_TransportRecvHCIEventSync); +EXPORT_SYMBOL(_HCI_TransportSetBaudRate); +EXPORT_SYMBOL(_HCI_TransportEnablePowerMgmt); diff --git a/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c b/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c new file mode 100644 index 000000000000..6087edcb1d6a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c @@ -0,0 +1,1141 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "wmi.h" +#include "a_drv.h" +#include "hif.h" +#include "common_drv.h" +#include "a_debug.h" +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) +#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) +#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) +#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) +#else +#include "ar6000_drv.h" +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +#ifdef ATH_AR6K_ENABLE_GMBOX +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include "export_hci_transport.h" +#else +#include "hci_transport_api.h" +#endif +#include "epping_test.h" +#include "gmboxif.h" +#include "ar3kconfig.h" +#include +#include + + /* only build on newer kernels which have BT configured */ +#if defined(CONFIG_BT_MODULE) || defined(CONFIG_BT) +#define CONFIG_BLUEZ_HCI_BRIDGE +#endif + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +unsigned int ar3khcibaud = 0; +unsigned int hciuartscale = 0; +unsigned int hciuartstep = 0; + +module_param(ar3khcibaud, int, 0644); +module_param(hciuartscale, int, 0644); +module_param(hciuartstep, int, 0644); +#else +extern unsigned int ar3khcibaud; +extern unsigned int hciuartscale; +extern unsigned int hciuartstep; +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +struct ar6k_hci_bridge_info { + void *pHCIDev; /* HCI bridge device */ + struct hci_transport_properties HCIProps; /* HCI bridge props */ + struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */ + bool HciNormalMode; /* Actual HCI mode enabled (non-TEST)*/ + bool HciRegistered; /* HCI device registered with stack */ + struct htc_packet_queue HTCPacketStructHead; + u8 *pHTCStructAlloc; + spinlock_t BridgeLock; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct hci_transport_misc_handles HCITransHdl; +#else + struct ar6_softc *ar; +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ +}; + +#define MAX_ACL_RECV_BUFS 16 +#define MAX_EVT_RECV_BUFS 8 +#define MAX_HCI_WRITE_QUEUE_DEPTH 32 +#define MAX_ACL_RECV_LENGTH 1200 +#define MAX_EVT_RECV_LENGTH 257 +#define TX_PACKET_RSV_OFFSET 32 +#define NUM_HTC_PACKET_STRUCTS ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2) + +#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) + +extern unsigned int setupbtdev; +struct ar3k_config_info ar3kconfig; + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +struct ar6k_hci_bridge_info *g_pHcidevInfo; +#endif + +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb); +static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length); +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb); + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar); +void ar6000_cleanup_hci(void *ar); +int hci_test_send(void *ar, struct sk_buff *skb); +#else +int ar6000_setup_hci(struct ar6_softc *ar); +void ar6000_cleanup_hci(struct ar6_softc *ar); +/* HCI bridge testing */ +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +#define LOCK_BRIDGE(dev) spin_lock_bh(&(dev)->BridgeLock) +#define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock) + +static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf) +{ + if (pHcidevInfo->HciNormalMode) { + bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf); + } else { + /* in test mode, these are just ordinary netbuf allocations */ + A_NETBUF_FREE(osbuf); + } +} + +static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket) +{ + LOCK_BRIDGE(pHcidevInfo); + HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket); + UNLOCK_BRIDGE(pHcidevInfo); +} + +static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + struct htc_packet *pPacket = NULL; + LOCK_BRIDGE(pHcidevInfo); + pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead); + UNLOCK_BRIDGE(pHcidevInfo); + return pPacket; +} + +#define BLOCK_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) + +static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + int NumBuffers) +{ + int length, i; + void *osBuf = NULL; + struct htc_packet_queue queue; + struct htc_packet *pPacket; + + INIT_HTC_PACKET_QUEUE(&queue); + + if (Type == HCI_ACL_TYPE) { + if (pHcidevInfo->HciNormalMode) { + length = HCI_MAX_FRAME_SIZE; + } else { + length = MAX_ACL_RECV_LENGTH; + } + } else { + length = MAX_EVT_RECV_LENGTH; + } + + /* add on transport head and tail room */ + length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; + /* round up to the required I/O padding */ + length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); + + for (i = 0; i < NumBuffers; i++) { + + if (pHcidevInfo->HciNormalMode) { + osBuf = bt_alloc_buffer(pHcidevInfo,length); + } else { + osBuf = A_NETBUF_ALLOC(length); + } + + if (NULL == osBuf) { + break; + } + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + FreeBtOsBuf(pHcidevInfo,osBuf); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); + break; + } + + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); + /* add to queue */ + HTC_PACKET_ENQUEUE(&queue,pPacket); + } + + if (i > 0) { + HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); + } +} + +#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ + (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) +static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE HCIHandle, + struct hci_transport_properties *pProps, + void *pContext) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + int status; + u32 address, hci_uart_pwr_mgmt_params; +// struct ar3k_config_info ar3kconfig; + + pHcidevInfo->pHCIDev = HCIHandle; + + memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps)); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", + (unsigned long)HCIHandle, + pHcidevInfo->HCIProps.HeadRoom, + pHcidevInfo->HCIProps.TailRoom, + pHcidevInfo->HCIProps.IOBlockPad)); + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len); +#else + A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len); +#endif + + /* provide buffers */ + RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS); + RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS); + + do { + /* start transport */ + status = HCI_TransportStart(pHcidevInfo->pHCIDev); + + if (status) { + break; + } + + if (!pHcidevInfo->HciNormalMode) { + /* in test mode, no need to go any further */ + break; + } + + // The delay is required when AR6K is driving the BT reset line + // where time is needed after the BT chip is out of reset (HCI_TransportStart) + // and before the first HCI command is issued (AR3KConfigure) + // FIXME + // The delay should be configurable and be only applied when AR6K driving the BT + // reset line. This could be done by some module parameter or based on some HW config + // info. For now apply 100ms delay blindly + A_MDELAY(100); + + A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); + ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev; + ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice); +#else + ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice; +#endif + ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; + + if (ar3khcibaud != 0) { + /* user wants ar3k baud rate change */ + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY; + ar3kconfig.AR3KBaudRate = ar3khcibaud; + } + + if ((hciuartscale != 0) || (hciuartstep != 0)) { + /* user wants to tune HCI bridge UART scale/step values */ + ar3kconfig.AR6KScale = (u16)hciuartscale; + ar3kconfig.AR6KStep = (u16)hciuartstep; + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP; + } + + /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */ + address = TARG_VTOP(pHcidevInfo->ar->arTargetType, + HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params)); + status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params); + if (0 == status) { + ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1); + ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16; + ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n")); + } + /* configure the AR3K device */ + memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6); + status = AR3KConfigure(&ar3kconfig); + if (status) { + break; + } + + /* Make sure both AR6K and AR3K have power management enabled */ + if (ar3kconfig.PwrMgmtEnabled) { + status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n")); + } + } + + status = bt_register_hci(pHcidevInfo); + + } while (false); + + return status; +} + +static void ar6000_hci_transport_failure(void *pContext, int Status) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n")); + + if (pHcidevInfo->HciNormalMode) { + /* TODO .. */ + } +} + +static void ar6000_hci_transport_removed(void *pContext) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n")); + + A_ASSERT(pHcidevInfo->pHCIDev != NULL); + + HCI_TransportDetach(pHcidevInfo->pHCIDev); + bt_cleanup_hci(pHcidevInfo); + pHcidevInfo->pHCIDev = NULL; +} + +static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + void *osbuf = pPacket->pPktContext; + A_ASSERT(osbuf != NULL); + A_ASSERT(pHcidevInfo != NULL); + + if (pPacket->Status) { + if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); + } + } + + FreeHTCStruct(pHcidevInfo,pPacket); + FreeBtOsBuf(pHcidevInfo,osbuf); + +} + +static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + struct sk_buff *skb; + + A_ASSERT(pHcidevInfo != NULL); + skb = (struct sk_buff *)pPacket->pPktContext; + A_ASSERT(skb != NULL); + + do { + + if (pPacket->Status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, + ("HCI Bridge, packet received type : %d len:%d \n", + HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength)); + + /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set + * to fill the front of the buffer */ + A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom); + A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n", + (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL", + skb->len)); + AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump"); + } + + if (pHcidevInfo->HciNormalMode) { + /* indicate the packet */ + if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) { + /* bt stack accepted the packet */ + skb = NULL; + } + break; + } + + /* for testing, indicate packet to the network stack */ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice); + if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) { + skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)); +#else + skb->dev = pHcidevInfo->ar->arNetDev; + if ((pHcidevInfo->ar->arNetDev->flags & IFF_UP) == IFF_UP) { + skb->protocol = eth_type_trans(skb, pHcidevInfo->ar->arNetDev); +#endif + netif_rx(skb); + skb = NULL; + } + + } while (false); + + FreeHTCStruct(pHcidevInfo,pPacket); + + if (skb != NULL) { + /* packet was not accepted, free it */ + FreeBtOsBuf(pHcidevInfo,skb); + } + +} + +static void ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + int refillCount; + + if (Type == HCI_ACL_TYPE) { + refillCount = MAX_ACL_RECV_BUFS - BuffersAvailable; + } else { + refillCount = MAX_EVT_RECV_BUFS - BuffersAvailable; + } + + if (refillCount > 0) { + RefillRecvBuffers(pHcidevInfo,Type,refillCount); + } + +} + +static HCI_SEND_FULL_ACTION ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + HCI_SEND_FULL_ACTION action = HCI_SEND_FULL_KEEP; + + if (!pHcidevInfo->HciNormalMode) { + /* for epping testing, check packet tag, some epping packets are + * special and cannot be dropped */ + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_DATA_PKT_TAG) { + action = HCI_SEND_FULL_DROP; + } + } + + return action; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar) +#else +int ar6000_setup_hci(struct ar6_softc *ar) +#endif +{ + struct hci_transport_config_info config; + int status = 0; + int i; + struct htc_packet *pPacket; + struct ar6k_hci_bridge_info *pHcidevInfo; + + + do { + + pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info)); + + if (NULL == pHcidevInfo) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info)); +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + g_pHcidevInfo = pHcidevInfo; + pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar; +#else + ar->hcidev_info = pHcidevInfo; + pHcidevInfo->ar = ar; +#endif + spin_lock_init(&pHcidevInfo->BridgeLock); + INIT_HTC_PACKET_QUEUE(&pHcidevInfo->HTCPacketStructHead); + + ar->exitCallback = AR3KConfigureExit; + + status = bt_setup_hci(pHcidevInfo); + if (status) { + break; + } + + if (pHcidevInfo->HciNormalMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in normal mode... \n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n")); + } + + pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS); + + if (NULL == pHcidevInfo->pHTCStructAlloc) { + status = A_NO_MEMORY; + break; + } + + pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc; + for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) { + FreeHTCStruct(pHcidevInfo,pPacket); + } + + A_MEMZERO(&config,sizeof(struct hci_transport_config_info)); + config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2; + config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2; + config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH; + config.pContext = pHcidevInfo; + config.TransportFailure = ar6000_hci_transport_failure; + config.TransportReady = ar6000_hci_transport_ready; + config.TransportRemoved = ar6000_hci_transport_removed; + config.pHCISendComplete = ar6000_hci_send_complete; + config.pHCIPktRecv = ar6000_hci_pkt_recv; + config.pHCIPktRecvRefill = ar6000_hci_pkt_refill; + config.pHCISendFull = ar6000_hci_pkt_send_full; + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + pHcidevInfo->pHCIDev = HCI_TransportAttach(pHcidevInfo->HCITransHdl.htcHandle, &config); +#else + pHcidevInfo->pHCIDev = HCI_TransportAttach(ar->arHtcTarget, &config); +#endif + + if (NULL == pHcidevInfo->pHCIDev) { + status = A_ERROR; + } + + } while (false); + + if (status) { + if (pHcidevInfo != NULL) { + if (NULL == pHcidevInfo->pHCIDev) { + /* GMBOX may not be present in older chips */ + /* just return success */ + status = 0; + } + } + ar6000_cleanup_hci(ar); + } + + return status; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_cleanup_hci(void *ar) +#else +void ar6000_cleanup_hci(struct ar6_softc *ar) +#endif +{ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; +#else + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; +#endif + + if (pHcidevInfo != NULL) { + bt_cleanup_hci(pHcidevInfo); + + if (pHcidevInfo->pHCIDev != NULL) { + HCI_TransportStop(pHcidevInfo->pHCIDev); + HCI_TransportDetach(pHcidevInfo->pHCIDev); + pHcidevInfo->pHCIDev = NULL; + } + + if (pHcidevInfo->pHTCStructAlloc != NULL) { + kfree(pHcidevInfo->pHTCStructAlloc); + pHcidevInfo->pHTCStructAlloc = NULL; + } + + kfree(pHcidevInfo); +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + ar->hcidev_info = NULL; +#endif + } + + +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int hci_test_send(void *ar, struct sk_buff *skb) +#else +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) +#endif +{ + int status = 0; + int length; + EPPING_HEADER *pHeader; + struct htc_packet *pPacket; + HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; +#else + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; +#endif + + do { + + if (NULL == pHcidevInfo) { + status = A_ERROR; + break; + } + + if (NULL == pHcidevInfo->pHCIDev) { + status = A_ERROR; + break; + } + + if (pHcidevInfo->HciNormalMode) { + /* this interface cannot run when normal WMI is running */ + status = A_ERROR; + break; + } + + pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); + + if (!IS_EPPING_PACKET(pHeader)) { + status = A_EINVAL; + break; + } + + if (IS_EPING_PACKET_NO_DROP(pHeader)) { + htc_tag = AR6K_CONTROL_PKT_TAG; + } + + length = sizeof(EPPING_HEADER) + pHeader->DataLength; + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + SET_HTC_PACKET_INFO_TX(pPacket, + skb, + A_NETBUF_DATA(skb), + length, + HCI_ACL_TYPE, /* send every thing out as ACL */ + htc_tag); + + HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); + pPacket = NULL; + + } while (false); + + return status; +} + +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; + struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig; + + config->pHCIDev = pHcidevInfo->pHCIDev; + config->pHCIProps = &pHcidevInfo->HCIProps; + config->pHIFDevice = ar->arHifDevice; + config->pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; + config->Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; + config->AR3KBaudRate = 115200; +} + +#ifdef CONFIG_BLUEZ_HCI_BRIDGE +/*** BT Stack Entrypoints *******/ + +/* + * bt_open - open a handle to the device +*/ +static int bt_open(struct hci_dev *hdev) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_open - enter - x\n")); + set_bit(HCI_RUNNING, &hdev->flags); + set_bit(HCI_UP, &hdev->flags); + set_bit(HCI_INIT, &hdev->flags); + return 0; +} + +/* + * bt_close - close handle to the device +*/ +static int bt_close(struct hci_dev *hdev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_close - enter\n")); + clear_bit(HCI_RUNNING, &hdev->flags); + return 0; +} + +/* + * bt_send_frame - send data frames +*/ +static int bt_send_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *)skb->dev; + HCI_TRANSPORT_PACKET_TYPE type; + struct ar6k_hci_bridge_info *pHcidevInfo; + struct htc_packet *pPacket; + int status = 0; + struct sk_buff *txSkb = NULL; + + if (!hdev) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_send_frame - no device\n")); + return -ENODEV; + } + + if (!test_bit(HCI_RUNNING, &hdev->flags)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_send_frame - not open\n")); + return -EBUSY; + } + + pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; + A_ASSERT(pHcidevInfo != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type)); + type = HCI_COMMAND_TYPE; + + switch (bt_cb(skb)->pkt_type) { + case HCI_COMMAND_PKT: + type = HCI_COMMAND_TYPE; + hdev->stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + type = HCI_ACL_TYPE; + hdev->stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + /* we don't support SCO over the bridge */ + kfree_skb(skb); + return 0; + default: + A_ASSERT(false); + kfree_skb(skb); + return 0; + } + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(">>> Send HCI %s packet len: %d\n", + (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL", + skb->len)); + if (type == HCI_COMMAND_TYPE) { + u16 opcode = HCI_GET_OP_CODE(skb->data); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" HCI Command: OGF:0x%X OCF:0x%X \r\n", + opcode >> 10, opcode & 0x3FF)); + } + AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump"); + } + + do { + + txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom + + pHcidevInfo->HCIProps.TailRoom + skb->len, + GFP_ATOMIC); + + if (txSkb == NULL) { + status = A_NO_MEMORY; + break; + } + + bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type; + txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev; + skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom); + memcpy(txSkb->data, skb->data, skb->len); + skb_put(txSkb,skb->len); + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + /* HCI packet length here doesn't include the 1-byte transport header which + * will be handled by the HCI transport layer. Enough headroom has already + * been reserved above for the transport header + */ + SET_HTC_PACKET_INFO_TX(pPacket, + txSkb, + txSkb->data, + txSkb->len, + type, + AR6K_CONTROL_PKT_TAG); /* HCI packets cannot be dropped */ + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: bt_send_frame skb:0x%lX \n",(unsigned long)txSkb)); + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n", + type, txSkb->len)); + + status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); + pPacket = NULL; + txSkb = NULL; + + } while (false); + + if (txSkb != NULL) { + kfree_skb(txSkb); + } + + kfree_skb(skb); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("-bt_send_frame \n")); + return 0; +} + +/* + * bt_ioctl - ioctl processing +*/ +static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_ioctl - enter\n")); + return -ENOIOCTLCMD; +} + +/* + * bt_flush - flush outstandingbpackets +*/ +static int bt_flush(struct hci_dev *hdev) +{ + struct ar6k_hci_bridge_info *pHcidevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n")); + + pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; + + /* TODO??? */ + + return 0; +} + + +/* + * bt_destruct - +*/ +static void bt_destruct(struct hci_dev *hdev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_destruct - enter\n")); + /* nothing to do here */ +} + +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int status = 0; + struct hci_dev *pHciDev = NULL; + struct hif_device_os_device_info osDevInfo; + + if (!setupbtdev) { + return 0; + } + + do { + + A_MEMZERO(&osDevInfo,sizeof(osDevInfo)); + /* get the underlying OS device */ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice), + &osDevInfo); +#else + status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, + HIF_DEVICE_GET_OS_DEVICE, + &osDevInfo, + sizeof(osDevInfo)); +#endif + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n")); + break; + } + + /* allocate a BT HCI struct for this device */ + pHciDev = hci_alloc_dev(); + if (NULL == pHciDev) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge - failed to allocate bt struct \n")); + status = A_NO_MEMORY; + break; + } + /* save the device, we'll register this later */ + pHcidevInfo->pBtStackHCIDev = pHciDev; + SET_HCIDEV_DEV(pHciDev,osDevInfo.pOSDevice); + SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_BREDR); + pHciDev->driver_data = pHcidevInfo; + pHciDev->open = bt_open; + pHciDev->close = bt_close; + pHciDev->send = bt_send_frame; + pHciDev->ioctl = bt_ioctl; + pHciDev->flush = bt_flush; + pHciDev->destruct = bt_destruct; + pHciDev->owner = THIS_MODULE; + /* driver is running in normal BT mode */ + pHcidevInfo->HciNormalMode = true; + + } while (false); + + if (status) { + bt_cleanup_hci(pHcidevInfo); + } + + return status; +} + +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int err; + + if (pHcidevInfo->HciRegistered) { + pHcidevInfo->HciRegistered = false; + clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags); + clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags); + clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags); + A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); + /* unregister */ + if ((err = hci_unregister_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to unregister with bluetooth %d\n",err)); + } + } + + kfree(pHcidevInfo->pBtStackHCIDev); + pHcidevInfo->pBtStackHCIDev = NULL; +} + +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int err; + int status = 0; + + do { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n")); + A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); + /* mark that we are registered */ + pHcidevInfo->HciRegistered = true; + if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err)); + pHcidevInfo->HciRegistered = false; + status = A_ERROR; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n")); + + } while (false); + + return status; +} + +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb) +{ + u8 btType; + int len; + bool success = false; + BT_HCI_EVENT_HEADER *pEvent; + + do { + + if (!test_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_indicate_recv - not running\n")); + break; + } + + switch (Type) { + case HCI_ACL_TYPE: + btType = HCI_ACLDATA_PKT; + break; + case HCI_EVENT_TYPE: + btType = HCI_EVENT_PKT; + break; + default: + btType = 0; + A_ASSERT(false); + break; + } + + if (0 == btType) { + break; + } + + /* set the final type */ + bt_cb(skb)->pkt_type = btType; + /* set dev */ + skb->dev = (void *)pHcidevInfo->pBtStackHCIDev; + len = skb->len; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_RECV)) { + if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { + pEvent = (BT_HCI_EVENT_HEADER *)skb->data; + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("BT HCI EventCode: %d, len:%d \n", + pEvent->EventCode, pEvent->ParamLength)); + } + } + + /* pass receive packet up the stack */ + if (hci_recv_frame(skb) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: hci_recv_frame failed \n")); + break; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, + ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len)); + } + + success = true; + + } while (false); + + return success; +} + +static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) +{ + struct sk_buff *skb; + /* in normal HCI mode we need to alloc from the bt core APIs */ + skb = bt_skb_alloc(Length, GFP_ATOMIC); + if (NULL == skb) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc bt sk_buff \n")); + } + return skb; +} + +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) +{ + kfree_skb(skb); +} + +#else // { CONFIG_BLUEZ_HCI_BRIDGE + + /* stubs when we only want to test the HCI bridging Interface without the HT stack */ +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + return 0; +} +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + +} +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + A_ASSERT(false); + return A_ERROR; +} + +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb) +{ + A_ASSERT(false); + return false; +} + +static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) +{ + A_ASSERT(false); + return NULL; +} +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) +{ + A_ASSERT(false); +} + +#endif // } CONFIG_BLUEZ_HCI_BRIDGE + +#else // { ATH_AR6K_ENABLE_GMBOX + + /* stubs when GMBOX support is not needed */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar) +#else +int ar6000_setup_hci(struct ar6_softc *ar) +#endif +{ + return 0; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_cleanup_hci(void *ar) +#else +void ar6000_cleanup_hci(struct ar6_softc *ar) +#endif +{ + return; +} + +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) +{ + return; +} +#endif + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int hci_test_send(void *ar, struct sk_buff *skb) +#else +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) +#endif +{ + return -EOPNOTSUPP; +} + +#endif // } ATH_AR6K_ENABLE_GMBOX + + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +static int __init +hcibridge_init_module(void) +{ + int status; + struct hci_transport_callbacks hciTransCallbacks; + + hciTransCallbacks.setupTransport = ar6000_setup_hci; + hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci; + + status = ar6000_register_hci_transport(&hciTransCallbacks); + if (status) + return -ENODEV; + + return 0; +} + +static void __exit +hcibridge_cleanup_module(void) +{ +} + +module_init(hcibridge_init_module); +module_exit(hcibridge_cleanup_module); +MODULE_LICENSE("Dual BSD/GPL"); +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h new file mode 100644 index 000000000000..80cef77738fb --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h @@ -0,0 +1,776 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6000_H_ +#define _AR6000_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "wmi.h" +#include "a_drv.h" +#include "bmi.h" +#include +#include +#include +#include +#include "pkt_log.h" +#include "aggr_recv_api.h" +#include +#include +#include +#include "ar6000_api.h" +#ifdef CONFIG_HOST_TCMD_SUPPORT +#include +#endif +#include + +#include "targaddrs.h" +#include "dbglog_api.h" +#include "ar6000_diag.h" +#include "common_drv.h" +#include "roaming.h" +#include "hci_transport_api.h" +#define ATH_MODULE_NAME driver +#include "a_debug.h" +#include "hw/apb_map.h" +#include "hw/rtc_reg.h" +#include "hw/mbox_reg.h" +#include "gpio_reg.h" + +#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) +#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) +#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) +#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) +#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) + +#ifndef __dev_put +#define __dev_put(dev) dev_put(dev) +#endif + + +#define USER_SAVEDKEYS_STAT_INIT 0 +#define USER_SAVEDKEYS_STAT_RUN 1 + +// TODO this needs to move into the AR_SOFTC struct +struct USER_SAVEDKEYS { + struct ieee80211req_key ucast_ik; + struct ieee80211req_key bcast_ik; + CRYPTO_TYPE keyType; + bool keyOk; +}; + +#define DBG_INFO 0x00000001 +#define DBG_ERROR 0x00000002 +#define DBG_WARNING 0x00000004 +#define DBG_SDIO 0x00000008 +#define DBG_HIF 0x00000010 +#define DBG_HTC 0x00000020 +#define DBG_WMI 0x00000040 +#define DBG_WMI2 0x00000080 +#define DBG_DRIVER 0x00000100 + +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) + + +int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); +int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_AR6000 1 +#define AR6000_MAX_RX_BUFFERS 16 +#define AR6000_BUFFER_SIZE 1664 +#define AR6000_MAX_AMSDU_RX_BUFFERS 4 +#define AR6000_AMSDU_REFILL_THRESHOLD 3 +#define AR6000_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128) +#define AR6000_MAX_RX_MESSAGE_SIZE (max(WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH,WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) + +#define AR6000_TX_TIMEOUT 10 +#define AR6000_ETH_ADDR_LEN 6 +#define AR6000_MAX_ENDPOINTS 4 +#define MAX_NODE_NUM 15 +/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ +#define MAX_DEF_COOKIE_NUM 180 +#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ +#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM) + +/* MAX_DEFAULT_SEND_QUEUE_DEPTH is used to set the default queue depth for the + * WMM send queues. If a queue exceeds this depth htc will query back to the + * OS specific layer by calling EpSendFull(). This gives the OS layer the + * opportunity to drop the packet if desired. Therefore changing + * MAX_DEFAULT_SEND_QUEUE_DEPTH does not affect resource utilization but + * does impact the threshold used to identify if a packet should be + * dropped. */ +#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) + +#define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1 +#define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1 +#define A_DISCONNECT_TIMER_INTERVAL 10 * 1000 +#define A_DEFAULT_LISTEN_INTERVAL 100 +#define A_MAX_WOW_LISTEN_INTERVAL 1000 + +enum { + DRV_HB_CHALLENGE = 0, + APP_HB_CHALLENGE +}; + +enum { + WLAN_INIT_MODE_NONE = 0, + WLAN_INIT_MODE_USR, + WLAN_INIT_MODE_UDEV, + WLAN_INIT_MODE_DRV +}; + +/* Suspend - configuration */ +enum { + WLAN_SUSPEND_CUT_PWR = 0, + WLAN_SUSPEND_DEEP_SLEEP, + WLAN_SUSPEND_WOW, + WLAN_SUSPEND_CUT_PWR_IF_BT_OFF +}; + +/* WiFi OFF - configuration */ +enum { + WLAN_OFF_CUT_PWR = 0, + WLAN_OFF_DEEP_SLEEP, +}; + +/* WLAN low power state */ +enum { + WLAN_POWER_STATE_ON = 0, + WLAN_POWER_STATE_CUT_PWR = 1, + WLAN_POWER_STATE_DEEP_SLEEP, + WLAN_POWER_STATE_WOW +}; + +/* WLAN WoW State */ +enum { + WLAN_WOW_STATE_NONE = 0, + WLAN_WOW_STATE_SUSPENDED, + WLAN_WOW_STATE_SUSPENDING +}; + + +typedef enum _AR6K_BIN_FILE { + AR6K_OTP_FILE, + AR6K_FIRMWARE_FILE, + AR6K_PATCH_FILE, + AR6K_BOARD_DATA_FILE, +} AR6K_BIN_FILE; + +#ifdef SETUPHCI_ENABLED +#define SETUPHCI_DEFAULT 1 +#else +#define SETUPHCI_DEFAULT 0 +#endif /* SETUPHCI_ENABLED */ + +#ifdef SETUPBTDEV_ENABLED +#define SETUPBTDEV_DEFAULT 1 +#else +#define SETUPBTDEV_DEFAULT 0 +#endif /* SETUPBTDEV_ENABLED */ + +#ifdef ENABLEUARTPRINT_SET +#define ENABLEUARTPRINT_DEFAULT 1 +#else +#define ENABLEUARTPRINT_DEFAULT 0 +#endif /* ENABLEARTPRINT_SET */ + +#ifdef ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER +#define NOHIFSCATTERSUPPORT_DEFAULT 1 +#else /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ +#define NOHIFSCATTERSUPPORT_DEFAULT 0 +#endif /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ + + +#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) + +#ifdef CONFIG_AR600x_BT_QCOM +#define ATH6KL_BT_DEV 1 +#elif defined(CONFIG_AR600x_BT_CSR) +#define ATH6KL_BT_DEV 2 +#else +#define ATH6KL_BT_DEV 3 +#endif + +#ifdef CONFIG_AR600x_DUAL_ANTENNA +#define ATH6KL_BT_ANTENNA 2 +#else +#define ATH6KL_BT_ANTENNA 1 +#endif + +#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ + +#ifdef AR600x_BT_AR3001 +#define AR3KHCIBAUD_DEFAULT 3000000 +#define HCIUARTSCALE_DEFAULT 1 +#define HCIUARTSTEP_DEFAULT 8937 +#else +#define AR3KHCIBAUD_DEFAULT 0 +#define HCIUARTSCALE_DEFAULT 0 +#define HCIUARTSTEP_DEFAULT 0 +#endif /* AR600x_BT_AR3001 */ + +#define WLAN_INIT_MODE_DEFAULT WLAN_INIT_MODE_DRV + +#define AR6K_PATCH_DOWNLOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV1_VERSION) { \ + (_param) = AR6003_REV1_PATCH_DOWNLOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_PATCH_DOWNLOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_DATA_DOWNLOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV1_VERSION) { \ + (_param) = AR6003_REV1_DATA_DOWNLOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_DATA_DOWNLOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_DATASET_PATCH_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_DATASET_PATCH_ADDRESS; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_DATASET_PATCH_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_APP_LOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_APP_LOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_APP_LOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_APP_START_OVERRIDE_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_APP_START_OVERRIDE; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_APP_START_OVERRIDE; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +/* AR6003 1.0 definitions */ +#define AR6003_REV1_VERSION 0x300002ba +#define AR6003_REV1_DATA_DOWNLOAD_ADDRESS AR6003_REV1_OTP_DATA_ADDRESS +#define AR6003_REV1_PATCH_DOWNLOAD_ADDRESS 0x57ea6c +#define AR6003_REV1_OTP_FILE "ath6k/AR6003/hw1.0/otp.bin.z77" +#define AR6003_REV1_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athwlan.bin.z77" +#define AR6003_REV1_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athtcmd_ram.bin" +#define AR6003_REV1_ART_FIRMWARE_FILE "ath6k/AR6003/hw1.0/device.bin" +#define AR6003_REV1_PATCH_FILE "ath6k/AR6003/hw1.0/data.patch.bin" +#define AR6003_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw1.0/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.WB31.bin" +#else +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.CUSTOM.bin" +#endif /* Board Data File */ + +/* AR6003 2.0 definitions */ +#define AR6003_REV2_VERSION 0x30000384 +#define AR6003_REV2_DATA_DOWNLOAD_ADDRESS AR6003_REV2_OTP_DATA_ADDRESS +#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 +#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" +#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" +#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" +#define AR6003_REV2_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.0/device.bin" +#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" +#define AR6003_REV2_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.0/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.WB31.bin" +#else +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.CUSTOM.bin" +#endif /* Board Data File */ + +/* AR6003 3.0 definitions */ +#define AR6003_REV3_VERSION 0x30000582 +#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" +#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" +#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" +#define AR6003_REV3_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/device.bin" +#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" +#define AR6003_REV3_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.WB31.bin" +#else +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.CUSTOM.bin" +#endif /* Board Data File */ + + +/* Power states */ +enum { + WLAN_PWR_CTRL_UP = 0, + WLAN_PWR_CTRL_CUT_PWR, + WLAN_PWR_CTRL_DEEP_SLEEP, + WLAN_PWR_CTRL_WOW, + WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED +}; + +/* HTC RAW streams */ +typedef enum _HTC_RAW_STREAM_ID { + HTC_RAW_STREAM_NOT_MAPPED = -1, + HTC_RAW_STREAM_0 = 0, + HTC_RAW_STREAM_1 = 1, + HTC_RAW_STREAM_2 = 2, + HTC_RAW_STREAM_3 = 3, + HTC_RAW_STREAM_NUM_MAX +} HTC_RAW_STREAM_ID; + +#define RAW_HTC_READ_BUFFERS_NUM 4 +#define RAW_HTC_WRITE_BUFFERS_NUM 4 + +#define HTC_RAW_BUFFER_SIZE 1664 + +typedef struct { + int currPtr; + int length; + unsigned char data[HTC_RAW_BUFFER_SIZE]; + struct htc_packet HTCPacket; +} raw_htc_buffer; + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* + * add TCMD_MODE besides wmi and bypasswmi + * in TCMD_MODE, only few TCMD releated wmi commands + * counld be hanlder + */ +enum { + AR6000_WMI_MODE = 0, + AR6000_BYPASS_MODE, + AR6000_TCMD_MODE, + AR6000_WLAN_MODE +}; +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + +struct ar_wep_key { + u8 arKeyIndex; + u8 arKeyLen; + u8 arKey[64]; +} ; + +struct ar_key { + u8 key[WLAN_MAX_KEY_LEN]; + u8 key_len; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + u8 seq_len; + u32 cipher; +}; + +enum { + SME_DISCONNECTED, + SME_CONNECTING, + SME_CONNECTED +}; + +struct ar_node_mapping { + u8 macAddress[6]; + u8 epId; + u8 txPending; +}; + +struct ar_cookie { + unsigned long arc_bp[2]; /* Must be first field */ + struct htc_packet HtcPkt; /* HTC packet wrapper */ + struct ar_cookie *arc_list_next; +}; + +struct ar_hb_chlng_resp { + A_TIMER timer; + u32 frequency; + u32 seqNum; + bool outstanding; + u8 missCnt; + u8 missThres; +}; + +/* Per STA data, used in AP mode */ +/*TODO: All this should move to OS independent dir */ + +#define STA_PWR_MGMT_MASK 0x1 +#define STA_PWR_MGMT_SHIFT 0x0 +#define STA_PWR_MGMT_AWAKE 0x0 +#define STA_PWR_MGMT_SLEEP 0x1 + +#define STA_SET_PWR_SLEEP(sta) (sta->flags |= (STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) +#define STA_CLR_PWR_SLEEP(sta) (sta->flags &= ~(STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) +#define STA_IS_PWR_SLEEP(sta) ((sta->flags >> STA_PWR_MGMT_SHIFT) & STA_PWR_MGMT_MASK) + +#define STA_PS_POLLED_MASK 0x1 +#define STA_PS_POLLED_SHIFT 0x1 +#define STA_SET_PS_POLLED(sta) (sta->flags |= (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) +#define STA_CLR_PS_POLLED(sta) (sta->flags &= ~(STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) +#define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) + +typedef struct { + u16 flags; + u8 mac[ATH_MAC_LEN]; + u8 aid; + u8 keymgmt; + u8 ucipher; + u8 auth; + u8 wpa_ie[IEEE80211_MAX_IE]; + A_NETBUF_QUEUE_T psq; /* power save q */ + A_MUTEX_T psqLock; +} sta_t; + +typedef struct ar6_raw_htc { + HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX]; + HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX]; + struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX]; + struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX]; + wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX]; + wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX]; + raw_htc_buffer raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM]; + raw_htc_buffer raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM]; + bool write_buffer_available[HTC_RAW_STREAM_NUM_MAX]; + bool read_buffer_available[HTC_RAW_STREAM_NUM_MAX]; +} AR_RAW_HTC_T; + +struct ar6_softc { + struct net_device *arNetDev; /* net_device pointer */ + void *arWmi; + int arTxPending[ENDPOINT_MAX]; + int arTotalTxDataPending; + u8 arNumDataEndPts; + bool arWmiEnabled; + bool arWmiReady; + bool arConnected; + HTC_HANDLE arHtcTarget; + void *arHifDevice; + spinlock_t arLock; + struct semaphore arSem; + int arSsidLen; + u_char arSsid[32]; + u8 arNextMode; + u8 arNetworkType; + u8 arDot11AuthMode; + u8 arAuthMode; + u8 arPairwiseCrypto; + u8 arPairwiseCryptoLen; + u8 arGroupCrypto; + u8 arGroupCryptoLen; + u8 arDefTxKeyIndex; + struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1]; + u8 arBssid[6]; + u8 arReqBssid[6]; + u16 arChannelHint; + u16 arBssChannel; + u16 arListenIntervalB; + u16 arListenIntervalT; + struct ar6000_version arVersion; + u32 arTargetType; + s8 arRssi; + u8 arTxPwr; + bool arTxPwrSet; + s32 arBitRate; + struct net_device_stats arNetStats; + struct iw_statistics arIwStats; + s8 arNumChannels; + u16 arChannelList[32]; + u32 arRegCode; + bool statsUpdatePending; + TARGET_STATS arTargetStats; + s8 arMaxRetries; + u8 arPhyCapability; +#ifdef CONFIG_HOST_TCMD_SUPPORT + u32 arTargetMode; + void *tcmd_rx_report; + int tcmd_rx_report_len; +#endif + AR6000_WLAN_STATE arWlanState; + struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; + u8 arIbssPsEnable; + u8 arNodeNum; + u8 arNexEpId; + struct ar_cookie *arCookieList; + u32 arCookieCount; + u32 arRateMask; + u8 arSkipScan; + u16 arBeaconInterval; + bool arConnectPending; + bool arWmmEnabled; + struct ar_hb_chlng_resp arHBChallengeResp; + u8 arKeepaliveConfigured; + u32 arMgmtFilter; + HTC_ENDPOINT_ID arAc2EpMapping[WMM_NUM_AC]; + bool arAcStreamActive[WMM_NUM_AC]; + u8 arAcStreamPriMap[WMM_NUM_AC]; + u8 arHiAcStreamActivePri; + u8 arEp2AcMapping[ENDPOINT_MAX]; + HTC_ENDPOINT_ID arControlEp; +#ifdef HTC_RAW_INTERFACE + AR_RAW_HTC_T *arRawHtc; +#endif + bool arNetQueueStopped; + bool arRawIfInit; + int arDeviceIndex; + struct common_credit_state_info arCreditStateInfo; + bool arWMIControlEpFull; + bool dbgLogFetchInProgress; + u8 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE]; + u32 log_cnt; + u32 dbglog_init_done; + u32 arConnectCtrlFlags; + s32 user_savedkeys_stat; + u32 user_key_ctrl; + struct USER_SAVEDKEYS user_saved_keys; + USER_RSSI_THOLD rssi_map[12]; + u8 arUserBssFilter; + u16 ap_profile_flag; /* AP mode */ + WMI_AP_ACL g_acl; /* AP mode */ + sta_t sta_list[AP_MAX_NUM_STA]; /* AP mode */ + u8 sta_list_index; /* AP mode */ + struct ieee80211req_key ap_mode_bkey; /* AP mode */ + A_NETBUF_QUEUE_T mcastpsq; /* power save q for Mcast frames */ + A_MUTEX_T mcastpsqLock; + bool DTIMExpired; /* flag to indicate DTIM expired */ + u8 intra_bss; /* enable/disable intra bss data forward */ + void *aggr_cntxt; +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + void *hcidev_info; +#endif + WMI_AP_MODE_STAT arAPStats; + u8 ap_hidden_ssid; + u8 ap_country_code[3]; + u8 ap_wmode; + u8 ap_dtim_period; + u16 ap_beacon_interval; + u16 arRTS; + u16 arACS; /* AP mode - Auto Channel Selection */ + struct htc_packet_queue amsdu_rx_buffer_queue; + bool bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */ + A_TIMER disconnect_timer; + u8 rxMetaVersion; +#ifdef WAPI_ENABLE + u8 arWapiEnable; +#endif + WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig; + WMI_BTCOEX_STATS_EVENT arBtcoexStats; + s32 (*exitCallback)(void *config); /* generic callback at AR6K exit */ + struct hif_device_os_device_info osDevInfo; + struct wireless_dev *wdev; + struct cfg80211_scan_request *scan_request; + struct ar_key keys[WMI_MAX_KEY_INDEX + 1]; + u32 smeState; + u16 arWlanPowerState; + bool arWlanOff; +#ifdef CONFIG_PM + u16 arWowState; + bool arBTOff; + bool arBTSharing; + u16 arSuspendConfig; + u16 arWlanOffConfig; + u16 arWow2Config; +#endif + u8 scan_triggered; + WMI_SCAN_PARAMS_CMD scParams; +#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 + u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE]; + u8 bdaddr[6]; + bool scanSpecificSsid; +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT + void *arApDev; +#endif + u8 arAutoAuthStage; + + u8 *fw_otp; + size_t fw_otp_len; + u8 *fw; + size_t fw_len; + u8 *fw_patch; + size_t fw_patch_len; + u8 *fw_data; + size_t fw_data_len; +}; + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +struct ar_virtual_interface { + struct net_device *arNetDev; /* net_device pointer */ + struct ar6_softc *arDev; /* ar device pointer */ + struct net_device *arStaNetDev; /* net_device pointer */ +}; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +static inline void *ar6k_priv(struct net_device *dev) +{ + return (wdev_priv(dev->ieee80211_ptr)); +} + +#define SET_HCI_BUS_TYPE(pHciDev, __bus, __type) do { \ + (pHciDev)->bus = (__bus); \ + (pHciDev)->dev_type = (__type); \ +} while(0) + +#define GET_INODE_FROM_FILEP(filp) \ + (filp)->f_path.dentry->d_inode + +#define arAc2EndpointID(ar,ac) (ar)->arAc2EpMapping[(ac)] +#define arSetAc2EndpointIDMap(ar,ac,ep) \ +{ (ar)->arAc2EpMapping[(ac)] = (ep); \ + (ar)->arEp2AcMapping[(ep)] = (ac); } +#define arEndpoint2Ac(ar,ep) (ar)->arEp2AcMapping[(ep)] + +#define arRawIfEnabled(ar) (ar)->arRawIfInit +#define arRawStream2EndpointID(ar,raw) (ar)->arRawHtc->arRaw2EpMapping[(raw)] +#define arSetRawStream2EndpointIDMap(ar,raw,ep) \ +{ (ar)->arRawHtc->arRaw2EpMapping[(raw)] = (ep); \ + (ar)->arRawHtc->arEp2RawMapping[(ep)] = (raw); } +#define arEndpoint2RawStreamID(ar,ep) (ar)->arRawHtc->arEp2RawMapping[(ep)] + +struct ar_giwscan_param { + char *current_ev; + char *end_buf; + u32 bytes_needed; + struct iw_request_info *info; +}; + +#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++) + +#define AR6000_SPIN_LOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled:AR6000_LOCK\n")); \ + } \ + spin_lock_bh(lock); \ +} while (0) + +#define AR6000_SPIN_UNLOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled: AR6000_UNLOCK\n")); \ + } \ + spin_unlock_bh(lock); \ +} while (0) + +void ar6000_init_profile_info(struct ar6_softc *ar); +void ar6000_install_static_wep_keys(struct ar6_softc *ar); +int ar6000_init(struct net_device *dev); +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); +void ar6000_TxDataCleanup(struct ar6_softc *ar); +int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev); +void ar6000_restart_endpoint(struct net_device *dev); +void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs); + +#ifdef HTC_RAW_INTERFACE + +#ifndef __user +#define __user +#endif + +int ar6000_htc_raw_open(struct ar6_softc *ar); +int ar6000_htc_raw_close(struct ar6_softc *ar); +ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t count); +ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t count); + +#endif /* HTC_RAW_INTERFACE */ + +/* AP mode */ +/*TODO: These routines should be moved to a file that is common across OS */ +sta_t * +ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr); + +sta_t * +ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid); + +u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason); + +/* HCI support */ + +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(struct ar6_softc *ar); +void ar6000_cleanup_hci(struct ar6_softc *ar); +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig); + +/* HCI bridge testing */ +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); +#endif + +ATH_DEBUG_DECLARE_EXTERN(htc); +ATH_DEBUG_DECLARE_EXTERN(wmi); +ATH_DEBUG_DECLARE_EXTERN(bmi); +ATH_DEBUG_DECLARE_EXTERN(hif); +ATH_DEBUG_DECLARE_EXTERN(wlan); +ATH_DEBUG_DECLARE_EXTERN(misc); + +extern u8 bcast_mac[]; +extern u8 null_mac[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _AR6000_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h new file mode 100644 index 000000000000..39e0873aff24 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// The software source and binaries included in this development package are +// licensed, not sold. You, or your company, received the package under one +// or more license agreements. The rights granted to you are specifically +// listed in these license agreement(s). All other rights remain with Atheros +// Communications, Inc., its subsidiaries, or the respective owner including +// those listed on the included copyright notices. Distribution of any +// portion of this package must be in strict compliance with the license +// agreement(s) terms. +// +// +// +// PAL driver for AR6003 +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _AR6K_PAL_H_ +#define _AR6K_PAL_H_ +#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) + +/* transmit packet reserve offset */ +#define TX_PACKET_RSV_OFFSET 32 +/* pal specific config structure */ +typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb); +typedef struct ar6k_pal_config_s +{ + ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt; +}ar6k_pal_config_t; + +void register_pal_cb(ar6k_pal_config_t *palConfig_p); +#endif /* _AR6K_PAL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h new file mode 100644 index 000000000000..184dbdb50495 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h @@ -0,0 +1,190 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6XAPI_LINUX_H +#define _AR6XAPI_LINUX_H +#ifdef __cplusplus +extern "C" { +#endif + +struct ar6_softc; + +void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, + u32 sw_ver, u32 abi_ver); +int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid); +void ar6000_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval, NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen,u8 *assocInfo); +void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus); +void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, + bool ismcast); +void ar6000_bitrate_rx(void *devt, s32 rateKbps); +void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList); +void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode); +void ar6000_txPwr_rx(void *devt, u8 txPwr); +void ar6000_keepalive_rx(void *devt, u8 configured); +void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, + WMI_NEIGHBOR_INFO *info); +void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num); +void ar6000_scanComplete_event(struct ar6_softc *ar, int status); +void ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len); +void ar6000_rssiThreshold_event(struct ar6_softc *ar, + WMI_RSSI_THRESHOLD_VAL newThreshold, + s16 rssi); +void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal); +void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication, + u8 statusCode, u8 *tspecSuggestion); +void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel); +void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source); +void +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl); + +void +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p); + +void +ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, + WMI_GET_WOW_LIST_REPLY *wow_reply); + +void ar6000_pmkid_list_event(void *devt, u8 numPMKID, + WMI_PMKID *pmkidList, u8 *bssidList); + +void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values); +void ar6000_gpio_data_rx(u32 reg_id, u32 value); +void ar6000_gpio_ack_rx(void); + +s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt); +s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi); +s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above); + +void ar6000_dbglog_init_done(struct ar6_softc *ar); + +#ifdef CONFIG_HOST_TCMD_SUPPORT +void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len); +#endif + +void ar6000_tx_retry_err_event(void *devt); + +void ar6000_snrThresholdEvent_rx(void *devt, + WMI_SNR_THRESHOLD_VAL newThreshold, + u8 snr); + +void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal); + + +void ar6000_ratemask_rx(void *devt, u32 ratemask); + +int ar6000_get_driver_cfg(struct net_device *dev, + u16 cfgParam, + void *result); +void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len); + +void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, + s8 *buffer, u32 length); + +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); + +void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid); + +void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active); +HTC_ENDPOINT_ID ar6000_ac2_endpoint_id ( void * devt, u8 ac); +u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep ); + +void ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len); + +void ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) ; + +void ar6000_dset_open_req(void *devt, + u32 id, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg); +void ar6000_dset_close(void *devt, u32 access_cookie); +void ar6000_dset_data_req(void *devt, + u32 access_cookie, + u32 offset, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg); + + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +void prof_count_rx(unsigned int addr, unsigned int count); +#endif + +u32 ar6000_getnodeAge (void); + +u32 ar6000_getclkfreq (void); + +int ar6000_ap_mode_profile_commit(struct ar6_softc *ar); + +struct ieee80211req_wpaie; +int +ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie); + +int is_iwioctl_allowed(u8 mode, u16 cmd); + +int is_xioctl_allowed(u8 mode, int cmd); + +void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid); + +void ar6000_dtimexpiry_event(struct ar6_softc *ar); + +void ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *cmd); +void ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *cmd); +void ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *cmd); +void ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd); + +#ifdef WAPI_ENABLE +int ap_set_wapi_key(struct ar6_softc *ar, void *ik); +void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac); +#endif + +int ar6000_connect_to_ap(struct ar6_softc *ar); +int ar6000_disconnect(struct ar6_softc *ar); +int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending); +int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state); +int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state); + +#ifdef CONFIG_PM +int ar6000_suspend_ev(void *context); +int ar6000_resume_ev(void *context); +int ar6000_power_change_ev(void *context, u32 config); +void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent); +#endif + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname); +int ar6000_remove_ap_interface(struct ar6_softc *ar); +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h new file mode 100644 index 000000000000..3d5f01da543f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h @@ -0,0 +1,1217 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _ATHDRV_LINUX_H +#define _ATHDRV_LINUX_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * There are two types of ioctl's here: Standard ioctls and + * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed + * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The + * arguments for every XIOCTL starts with a 32-bit command word + * that is used to select which extended ioctl is in use. After + * the command word are command-specific arguments. + */ + +/* Linux standard Wireless Extensions, private ioctl interfaces */ +#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) +#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) +#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) +#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) +#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) +#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) +//#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+6) +//#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+7) +//#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+8) +//#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+9) +//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10) +#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) + + + +/* ====WMI Ioctls==== */ +/* + * + * Many ioctls simply provide WMI services to application code: + * an application makes such an ioctl call with a set of arguments + * that are packaged into the corresponding WMI message, and sent + * to the Target. + */ + +#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) +/* + * arguments: + * ar6000_version *revision + */ + +#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) +/* + * arguments: + * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h) + * uses: WMI_SET_POWER_MODE_CMDID + */ + +#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) +/* + * arguments: + * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h) + * uses: WMI_SET_SCAN_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) +/* + * arguments: + * UINT32 listenInterval + * uses: WMI_SET_LISTEN_INT_CMDID + */ + +#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) +/* + * arguments: + * WMI_BSS_FILTER filter (see include/wmi.h) + * uses: WMI_SET_BSS_FILTER_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) +/* + * arguments: + * WMI_CHANNEL_PARAMS_CMD chParams + * uses: WMI_SET_CHANNEL_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) +/* + * arguments: + * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h) + * uses: WMI_SETPROBED_SSID_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) +/* + * arguments: + * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h) + * uses: WMI_SET_POWER_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) +/* + * arguments: + * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h) + * uses: WMI_ADD_BAD_AP_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) +/* + * arguments: + * ar6000_queuereq queueRequest (see below) + */ + +#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) +/* + * arguments: + * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h) + * uses: WMI_CREATE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) +/* + * arguments: + * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h) + * uses: WMI_DELETE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) +/* + * arguments: + * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24) +/* + * arguments: + * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h) + * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) +/* + * arguments: + * TARGET_STATS *targetStats (see below) + * uses: WMI_GET_STATISTICS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) +/* + * arguments: + * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd + * uses: WMI_SET_ASSOC_INFO_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) +/* + * arguments: + * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h) + * uses: WMI_SET_ACCESS_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) +/* + * arguments: + * UINT32 beaconMissTime + * uses: WMI_SET_BMISS_TIME_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) +/* + * arguments: + * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h) + * uses: WMI_SET_DISC_TIMEOUT_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) +/* + * arguments: + * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd + * uses: WMI_SET_IBSS_PM_CAPS_CMDID + */ + +/* + * There is a very small space available for driver-private + * wireless ioctls. In order to circumvent this limitation, + * we multiplex a bunch of ioctls (XIOCTLs) on top of a + * single AR6000_IOCTL_EXTENDED ioctl. + */ +#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31) + + +/* ====BMI Extended Ioctls==== */ + +#define AR6000_XIOCTL_BMI_DONE 1 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_DONE) + * uses: BMI_DONE + */ + +#define AR6000_XIOCTL_BMI_READ_MEMORY 2 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY) + * UINT32 address + * UINT32 length + * } + * char results[length] + * } + * uses: BMI_READ_MEMORY + */ + +#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY) + * UINT32 address + * UINT32 length + * char data[length] + * uses: BMI_WRITE_MEMORY + */ + +#define AR6000_XIOCTL_BMI_EXECUTE 4 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE) + * UINT32 TargetAddress + * UINT32 parameter + * uses: BMI_EXECUTE + */ + +#define AR6000_XIOCTL_BMI_SET_APP_START 5 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START) + * UINT32 TargetAddress + * uses: BMI_SET_APP_START + */ + +#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * } + * UINT32 result + * } + * uses: BMI_READ_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * UINT32 newValue + * } + * uses: BMI_WRITE_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_TEST 8 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_TEST) + * UINT32 address + * UINT32 length + * UINT32 count + */ + + + +/* Historical Host-side DataSet support */ +#define AR6000_XIOCTL_UNUSED9 9 +#define AR6000_XIOCTL_UNUSED10 10 +#define AR6000_XIOCTL_UNUSED11 11 + +/* ====Misc Extended Ioctls==== */ + +#define AR6000_XIOCTL_FORCE_TARGET_RESET 12 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET) + */ + + +#ifdef HTC_RAW_INTERFACE +/* HTC Raw Interface Ioctls */ +#define AR6000_XIOCTL_HTC_RAW_OPEN 13 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN) + */ + +#define AR6000_XIOCTL_HTC_RAW_CLOSE 14 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE) + */ + +#define AR6000_XIOCTL_HTC_RAW_READ 15 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ) + * UINT32 mailboxID + * UINT32 length + * } + * results[length] + * } + */ + +#define AR6000_XIOCTL_HTC_RAW_WRITE 16 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE) + * UINT32 mailboxID + * UINT32 length + * char buffer[length] + */ +#endif /* HTC_RAW_INTERFACE */ + +#define AR6000_XIOCTL_CHECK_TARGET_READY 17 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY) + */ + + + +/* ====GPIO (General Purpose I/O) Extended Ioctls==== */ + +#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET) + * ar6000_gpio_output_set_cmd_s (see below) + * uses: WMIX_GPIO_OUTPUT_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INPUT_GET 19 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET) + * uses: WMIX_GPIO_INPUT_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_SET 20 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_GET 21 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_ACK 22 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK) + * ar6000_cpio_intr_ack_cmd_s (see below) + * uses: WMIX_GPIO_INTR_ACK_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_WAIT 23 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT) + */ + + + +/* ====more wireless commands==== */ + +#define AR6000_XIOCTL_SET_ADHOC_BSSID 24 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID) + * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h) + */ + +#define AR6000_XIOCTL_SET_OPT_MODE 25 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE) + * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h) + * uses: WMI_SET_OPT_MODE_CMDID + */ + +#define AR6000_XIOCTL_OPT_SEND_FRAME 26 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME) + * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h) + * uses: WMI_OPT_TX_FRAME_CMDID + */ + +#define AR6000_XIOCTL_SET_BEACON_INTVAL 27 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_BEACON_INTVAL) + * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h) + * uses: WMI_SET_BEACON_INT_CMDID + */ + + +#define IEEE80211_IOCTL_SETAUTHALG 28 + + +#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE) + * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h) + * uses: WMI_SET_VOICE_PKT_SIZE_CMDID + */ + + +#define AR6000_XIOCTL_SET_MAX_SP 30 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP) + * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h) + * uses: WMI_SET_MAX_SP_LEN_CMDID + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 + +#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 + +#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 + + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS) + * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h) + * WMI_SET_POWERSAVE_TIMERS_CMDID + */ + +#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE) + */ + +#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 +typedef enum { + WLAN_DISABLED, + WLAN_ENABLED +} AR6000_WLAN_STATE; +/* + * arguments: + * enable/disable + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 + +#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 +/* + * arguments: + * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd + * uses: WMI_SET_RETRY_LIMITS_CMDID + */ + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* ====extended commands for radio test ==== */ + +#define AR6000_XIOCTL_TCMD_CONT_TX 38 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX) + * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h) + * uses: WMI_TCMD_CONT_TX_CMDID + */ + +#define AR6000_XIOCTL_TCMD_CONT_RX 39 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX) + * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h) + * uses: WMI_TCMD_CONT_RX_CMDID + */ + +#define AR6000_XIOCTL_TCMD_PM 40 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_PM) + * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h) + * uses: WMI_TCMD_PM_CMDID + */ + +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + +#define AR6000_XIOCTL_WMI_STARTSCAN 41 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN) + * UINT8 scanType + * UINT8 scanConnected + * u32 forceFgScan + * uses: WMI_START_SCAN_CMDID + */ + +#define AR6000_XIOCTL_WMI_SETFIXRATES 42 + +#define AR6000_XIOCTL_WMI_GETFIXRATES 43 + + +#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 +/* + * arguments: + * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45 +/* + * arguments: + * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h) + * uses: WMI_CLR_RSSISNR_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 +/* + * arguments: + * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_RTS 47 +/* + * arguments: + * WMI_SET_RTS_MODE_CMD (see include/wmi.h) + * uses: WMI_SET_RTS_MODE_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 + +#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE) + * UINT8 mode + * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM) + * UINT8 mode + * uses: WMI_SET_WMM_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_WMM 51 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS) + * UINT32 frequency + * UINT8 threshold + */ +#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP) + * UINT32 cookie + */ +#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD) + * UINT32 regDomain + */ +#define AR6000_XIOCTL_WMI_GET_RD 54 + +#define AR6000_XIOCTL_DIAG_READ 55 + +#define AR6000_XIOCTL_DIAG_WRITE 56 + +/* + * arguments cmd (AR6000_XIOCTL_SET_TXOP) + * WMI_TXOP_CFG txopEnable + */ +#define AR6000_XIOCTL_WMI_SET_TXOP 57 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS) + * UINT32 keyOpCtrl + * uses struct ar6000_user_setkeys_info + */ +#define AR6000_XIOCTL_USER_SETKEYS 58 + +#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 +/* + * arguments: + * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE) + * UINT8 keepaliveInterval + * uses: WMI_SET_KEEPALIVE_CMDID + */ + +#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 +/* + * arguments: + * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE) + * UINT8 keepaliveInterval + * u32 configured + * uses: WMI_GET_KEEPALIVE_CMDID + */ + +/* ====ROM Patching Extended Ioctls==== */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL) + * UINT32 ROM Address + * UINT32 RAM Address + * UINT32 number of bytes + * UINT32 activate? (0 or 1) + * } + * u32 resulting rompatch ID + * } + * uses: BMI_ROMPATCH_INSTALL + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL) + * UINT32 rompatch ID + * } + * uses: BMI_ROMPATCH_UNINSTALL + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) + * UINT32 rompatch count + * UINT32 rompatch IDs[rompatch count] + * } + * uses: BMI_ROMPATCH_ACTIVATE + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE) + * UINT32 rompatch count + * UINT32 rompatch IDs[rompatch count] + * } + * uses: BMI_ROMPATCH_DEACTIVATE + */ + +#define AR6000_XIOCTL_WMI_SET_APPIE 65 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE) + * UINT32 app_frmtype; + * UINT32 app_buflen; + * UINT8 app_buf[]; + * } + */ +#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 +/* + * arguments: + * u32 filter_type; + */ + +#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 + +#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 + +#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 +/* + * arguments: + * u32 wsc_status; + * (WSC_REG_INACTIVE or WSC_REG_ACTIVE) + */ + +/* + * arguments: + * struct { + * u8 streamType; + * u8 status; + * } + * uses: WMI_SET_BT_STATUS_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71 + +/* + * arguments: + * struct { + * u8 paramType; + * union { + * u8 noSCOPkts; + * BT_PARAMS_A2DP a2dpParams; + * BT_COEX_REGS regs; + * }; + * } + * uses: WMI_SET_BT_PARAM_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 + +#define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 +#define AR6000_XIOCTL_WMI_SET_WOW_MODE 74 +#define AR6000_XIOCTL_WMI_GET_WOW_LIST 75 +#define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 +#define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 + + + +#define AR6000_XIOCTL_TARGET_INFO 78 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO) + * u32 TargetVersion (returned) + * u32 TargetType (returned) + * (See also bmi_msg.h target_ver and target_type) + */ + +#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 +/* + * arguments: + * none + */ + +#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 +/* + * This ioctl is used to emulate traffic activity + * timeouts. Activity/inactivity will trigger the driver + * to re-balance credits. + * + * arguments: + * ar6000_traffic_activity_change + */ + +#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 +/* + * This ioctl is used to set the connect control flags + * + * arguments: + * u32 connectCtrlFlags + */ + +#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 +/* + * This IOCTL sets any Authentication,Key Management and Protection + * related parameters. This is used along with the information set in + * Connect Command. + * Currently this enables Multiple PMKIDs to an AP. + * + * arguments: + * struct { + * u32 akmpInfo; + * } + * uses: WMI_SET_AKMP_PARAMS_CMD + */ + +#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 + +#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 +/* + * This IOCTL is used to set a list of PMKIDs. This list of + * PMKIDs is used in the [Re]AssocReq Frame. This list is used + * only if the MultiPMKID option is enabled via the + * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL. + * + * arguments: + * struct { + * u32 numPMKID; + * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; + * } + * uses: WMI_SET_PMKIDLIST_CMD + */ + +#define AR6000_XIOCTL_WMI_SET_PARAMS 85 +#define AR6000_XIOCTL_WMI_SET_MCAST_FILTER 86 +#define AR6000_XIOCTL_WMI_DEL_MCAST_FILTER 87 + + +/* Historical DSETPATCH support for INI patches */ +#define AR6000_XIOCTL_UNUSED90 90 + + +/* Support LZ-compressed firmware download */ +#define AR6000_XIOCTL_BMI_LZ_STREAM_START 91 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_STREAM_START) + * UINT32 address + * uses: BMI_LZ_STREAM_START + */ + +#define AR6000_XIOCTL_BMI_LZ_DATA 92 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_DATA) + * UINT32 length + * char data[length] + * uses: BMI_LZ_DATA + */ + +#define AR6000_XIOCTL_PROF_CFG 93 +/* + * arguments: + * u32 period + * u32 nbins + */ + +#define AR6000_XIOCTL_PROF_ADDR_SET 94 +/* + * arguments: + * u32 Target address + */ + +#define AR6000_XIOCTL_PROF_START 95 + +#define AR6000_XIOCTL_PROF_STOP 96 + +#define AR6000_XIOCTL_PROF_COUNT_GET 97 + +#define AR6000_XIOCTL_WMI_ABORT_SCAN 98 + +/* + * AP mode + */ +#define AR6000_XIOCTL_AP_GET_STA_LIST 99 + +#define AR6000_XIOCTL_AP_HIDDEN_SSID 100 + +#define AR6000_XIOCTL_AP_SET_NUM_STA 101 + +#define AR6000_XIOCTL_AP_SET_ACL_MAC 102 + +#define AR6000_XIOCTL_AP_GET_ACL_LIST 103 + +#define AR6000_XIOCTL_AP_COMMIT_CONFIG 104 + +#define IEEE80211_IOCTL_GETWPAIE 105 + +#define AR6000_XIOCTL_AP_CONN_INACT_TIME 106 + +#define AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 + +#define AR6000_XIOCTL_AP_SET_COUNTRY 108 + +#define AR6000_XIOCTL_AP_SET_DTIM 109 + + + + +#define AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 + +#define AR6000_XIOCTL_SET_IP 111 + +#define AR6000_XIOCTL_AP_SET_ACL_POLICY 112 + +#define AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 + +#define AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 + +#define AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 + +#define AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 + +#define AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 + +#define AR6000_XIOCTL_SET_HT_CAP 118 + +#define AR6000_XIOCTL_SET_HT_OP 119 + +#define AR6000_XIOCTL_AP_GET_STAT 120 + +#define AR6000_XIOCTL_SET_TX_SELECT_RATES 121 + +#define AR6000_XIOCTL_SETUP_AGGR 122 + +#define AR6000_XIOCTL_ALLOW_AGGR 123 + +#define AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 + +#define AR6000_XIOCTL_AP_GET_COUNTRY 125 + +#define AR6000_XIOCTL_AP_GET_WMODE 126 + +#define AR6000_XIOCTL_AP_GET_DTIM 127 + +#define AR6000_XIOCTL_AP_GET_BINTVL 128 + +#define AR6000_XIOCTL_AP_GET_RTS 129 + +#define AR6000_XIOCTL_DELE_AGGR 130 + +#define AR6000_XIOCTL_FETCH_TARGET_REGS 131 + +#define AR6000_XIOCTL_HCI_CMD 132 + +#define AR6000_XIOCTL_ACL_DATA 133 /* used to be used for PAL */ + +#define AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 + +#define AR6000_XIOCTL_AP_SET_11BG_RATESET 135 + +/* + * arguments: + * WMI_AP_PS_CMD apPsCmd + * uses: WMI_AP_PS_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_AP_PS 136 + +#define AR6000_XIOCTL_WMI_MCAST_FILTER 137 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 + +#define AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 + +#define AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 + +#define AR6000_XIOCTL_WMI_GET_BTCOEX_STATS 147 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_QOS_SUPP) + * UINT8 mode + * uses: WMI_SET_QOS_SUPP_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 + +#define AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 + +#define AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 + +#define AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 + +#define AR6000_XIOCTL_ADD_AP_INTERFACE 152 + +#define AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 + +#define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 + +#define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 + +/* used by AR6000_IOCTL_WMI_GETREV */ +struct ar6000_version { + u32 host_ver; + u32 target_ver; + u32 wlan_ver; + u32 abi_ver; +}; + +/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */ +struct ar6000_queuereq { + u8 trafficClass; + u16 activeTsids; +}; + +/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */ +typedef struct targetStats_t { + u64 tx_packets; + u64 tx_bytes; + u64 tx_unicast_pkts; + u64 tx_unicast_bytes; + u64 tx_multicast_pkts; + u64 tx_multicast_bytes; + u64 tx_broadcast_pkts; + u64 tx_broadcast_bytes; + u64 tx_rts_success_cnt; + u64 tx_packet_per_ac[4]; + + u64 tx_errors; + u64 tx_failed_cnt; + u64 tx_retry_cnt; + u64 tx_mult_retry_cnt; + u64 tx_rts_fail_cnt; + + u64 rx_packets; + u64 rx_bytes; + u64 rx_unicast_pkts; + u64 rx_unicast_bytes; + u64 rx_multicast_pkts; + u64 rx_multicast_bytes; + u64 rx_broadcast_pkts; + u64 rx_broadcast_bytes; + u64 rx_fragment_pkt; + + u64 rx_errors; + u64 rx_crcerr; + u64 rx_key_cache_miss; + u64 rx_decrypt_err; + u64 rx_duplicate_frames; + + u64 tkip_local_mic_failure; + u64 tkip_counter_measures_invoked; + u64 tkip_replays; + u64 tkip_format_errors; + u64 ccmp_format_errors; + u64 ccmp_replays; + + u64 power_save_failure_cnt; + + u64 cs_bmiss_cnt; + u64 cs_lowRssi_cnt; + u64 cs_connect_cnt; + u64 cs_disconnect_cnt; + + s32 tx_unicast_rate; + s32 rx_unicast_rate; + + u32 lq_val; + + u32 wow_num_pkts_dropped; + u16 wow_num_events_discarded; + + s16 noise_floor_calibation; + s16 cs_rssi; + s16 cs_aveBeacon_rssi; + u8 cs_aveBeacon_snr; + u8 cs_lastRoam_msec; + u8 cs_snr; + + u8 wow_num_host_pkt_wakeups; + u8 wow_num_host_event_wakeups; + + u32 arp_received; + u32 arp_matched; + u32 arp_replied; +}TARGET_STATS; + +typedef struct targetStats_cmd_t { + TARGET_STATS targetStats; + int clearStats; +} TARGET_STATS_CMD; + +/* used by AR6000_XIOCTL_USER_SETKEYS */ + +/* + * Setting this bit to 1 doesnot initialize the RSC on the firmware + */ +#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1 +#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002 + +struct ar6000_user_setkeys_info { + u32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */ +}; /* XXX: unused !? */ + +/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */ +struct ar6000_gpio_output_set_cmd_s { + u32 set_mask; + u32 clear_mask; + u32 enable_mask; + u32 disable_mask; +}; + +/* + * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET + */ +struct ar6000_gpio_register_cmd_s { + u32 gpioreg_id; + u32 value; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_ACK */ +struct ar6000_gpio_intr_ack_cmd_s { + u32 ack_mask; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */ +struct ar6000_gpio_intr_wait_cmd_s { + u32 intr_mask; + u32 input_values; +}; + +/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */ +typedef struct ar6000_dbglog_module_config_s { + u32 valid; + u16 mmask; + u16 tsr; + u32 rep; + u16 size; +} DBGLOG_MODULE_CONFIG; + +typedef struct user_rssi_thold_t { + s16 tag; + s16 rssi; +} USER_RSSI_THOLD; + +typedef struct user_rssi_params_t { + u8 weight; + u32 pollTime; + USER_RSSI_THOLD tholds[12]; +} USER_RSSI_PARAMS; + +typedef struct ar6000_get_btcoex_config_cmd_t{ + u32 btProfileType; + u32 linkId; + }AR6000_GET_BTCOEX_CONFIG_CMD; + +typedef struct ar6000_btcoex_config_t { + AR6000_GET_BTCOEX_CONFIG_CMD configCmd; + u32 *configEvent; +} AR6000_BTCOEX_CONFIG; + +typedef struct ar6000_btcoex_stats_t { + u32 *statsEvent; + }AR6000_BTCOEX_STATS; +/* + * Host driver may have some config parameters. Typically, these + * config params are one time config parameters. These could + * correspond to any of the underlying modules. Host driver exposes + * an api for the underlying modules to get this config. + */ +#define AR6000_DRIVER_CFG_BASE 0x8000 + +/* Should driver perform wlan node caching? */ +#define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001 +/*Should we log raw WMI msgs */ +#define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002 + +/* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */ +struct ar6000_diag_window_cmd_s { + unsigned int addr; + unsigned int value; +}; + + +struct ar6000_traffic_activity_change { + u32 StreamID; /* stream ID to indicate activity change */ + u32 Active; /* active (1) or inactive (0) */ +}; + +/* Used with AR6000_XIOCTL_PROF_COUNT_GET */ +struct prof_count_s { + u32 addr; /* bin start address */ + u32 count; /* hit count */ +}; + + +/* used by AR6000_XIOCTL_MODULE_DEBUG_SET_MASK */ +/* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */ +/* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */ +struct drv_debug_module_s { + char modulename[128]; /* name of module */ + u32 mask; /* new mask to set .. or .. current mask */ +}; + + +/* All HCI related rx events are sent up to the host app + * via a wmi event id. It can contain ACL data or HCI event, + * based on which it will be de-multiplexed. + */ +typedef enum { + PAL_HCI_EVENT = 0, + PAL_HCI_RX_DATA, +} WMI_PAL_EVENT_INFO; + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h new file mode 100644 index 000000000000..d5253207b198 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6K_CFG80211_H_ +#define _AR6K_CFG80211_H_ + +struct wireless_dev *ar6k_cfg80211_init(struct device *dev); +void ar6k_cfg80211_deinit(struct ar6_softc *ar); + +void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status); + +void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval,NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen, u8 *assocInfo); + +void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus); + +void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast); + +#ifdef CONFIG_NL80211_TESTMODE +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len); +#else +static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar, + void *buf, int buf_len) +{ +} +#endif + + +#endif /* _AR6K_CFG80211_H_ */ + + + + + + diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h new file mode 100644 index 000000000000..dbbe1a00b92c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _CONFIG_LINUX_H_ +#define _CONFIG_LINUX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Host side Test Command support + */ +#define CONFIG_HOST_TCMD_SUPPORT + +#define USE_4BYTE_REGISTER_ACCESS + +/* Host-side support for Target-side profiling */ +#undef CONFIG_TARGET_PROFILE_SUPPORT + +/* IP/TCP checksum offload */ +/* Checksum offload is currently not supported for 64 bit platforms */ +#ifndef __LP64__ +#define CONFIG_CHECKSUM_OFFLOAD +#endif /* __LP64__ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h new file mode 100644 index 000000000000..b8dba52badce --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _DEBUG_LINUX_H_ +#define _DEBUG_LINUX_H_ + + /* macro to remove parens */ +#define ATH_PRINTX_ARG(arg...) arg + +#ifdef DEBUG + /* NOTE: the AR_DEBUG_PRINTF macro is defined here to handle special handling of variable arg macros + * which may be compiler dependent. */ +#define AR_DEBUG_PRINTF(mask, args) do { \ + if (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (mask)) { \ + A_LOGGER(mask, ATH_MODULE_NAME, ATH_PRINTX_ARG args); \ + } \ +} while (0) +#else + /* on non-debug builds, keep in error and warning messages in the driver, all other + * message tracing will get compiled out */ +#define AR_DEBUG_PRINTF(mask, args) \ + if ((mask) & (ATH_DEBUG_ERR | ATH_DEBUG_WARN)) { A_PRINTF(ATH_PRINTX_ARG args); } + +#endif + + /* compile specific macro to get the function name string */ +#define _A_FUNCNAME_ __func__ + + +#endif /* _DEBUG_LINUX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h b/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h new file mode 100644 index 000000000000..74f986183347 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include "hci_transport_api.h" +#include "common_drv.h" + +extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); +extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); +extern int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); +extern void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); +extern int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); +extern int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); +extern int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + + +#define HCI_TransportAttach(HTCHandle, pInfo) \ + _HCI_TransportAttach((HTCHandle), (pInfo)) +#define HCI_TransportDetach(HciTrans) \ + _HCI_TransportDetach(HciTrans) +#define HCI_TransportAddReceivePkts(HciTrans, pQueue) \ + _HCI_TransportAddReceivePkts((HciTrans), (pQueue)) +#define HCI_TransportSendPkt(HciTrans, pPacket, Synchronous) \ + _HCI_TransportSendPkt((HciTrans), (pPacket), (Synchronous)) +#define HCI_TransportStop(HciTrans) \ + _HCI_TransportStop((HciTrans)) +#define HCI_TransportStart(HciTrans) \ + _HCI_TransportStart((HciTrans)) +#define HCI_TransportEnableDisableAsyncRecv(HciTrans, Enable) \ + _HCI_TransportEnableDisableAsyncRecv((HciTrans), (Enable)) +#define HCI_TransportRecvHCIEventSync(HciTrans, pPacket, MaxPollMS) \ + _HCI_TransportRecvHCIEventSync((HciTrans), (pPacket), (MaxPollMS)) +#define HCI_TransportSetBaudRate(HciTrans, Baud) \ + _HCI_TransportSetBaudRate((HciTrans), (Baud)) +#define HCI_TransportEnablePowerMgmt(HciTrans, Enable) \ + _HCI_TransportEnablePowerMgmt((HciTrans), (Enable)) + + +extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks); + +extern int ar6000_get_hif_dev(struct hif_device *device, void *config); + +extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step); + +/* get core clock register settings + * data: 0 - 40/44MHz + * 1 - 80/88MHz + * where (5G band/2.4G band) + * assume 2.4G band for now + */ +extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data); diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h new file mode 100644 index 000000000000..e6e96de3fc6b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h @@ -0,0 +1,177 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _IEEE80211_IOCTL_H_ +#define _IEEE80211_IOCTL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Extracted from the MADWIFI net80211/ieee80211_ioctl.h + */ + +/* + * WPA/RSN get/set key request. Specify the key/cipher + * type and whether the key is to be used for sending and/or + * receiving. The key index should be set only when working + * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). + * Otherwise a unicast/pairwise key is specified by the bssid + * (on a station) or mac address (on an ap). They key length + * must include any MIC key data; otherwise it should be no + more than IEEE80211_KEYBUF_SIZE. + */ +struct ieee80211req_key { + u_int8_t ik_type; /* key/cipher type */ + u_int8_t ik_pad; + u_int16_t ik_keyix; /* key index */ + u_int8_t ik_keylen; /* key length in bytes */ + u_int8_t ik_flags; +#define IEEE80211_KEY_XMIT 0x01 +#define IEEE80211_KEY_RECV 0x02 +#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */ + u_int8_t ik_macaddr[IEEE80211_ADDR_LEN]; + u_int64_t ik_keyrsc; /* key receive sequence counter */ + u_int64_t ik_keytsc; /* key transmit sequence counter */ + u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; +}; +/* + * Delete a key either by index or address. Set the index + * to IEEE80211_KEYIX_NONE when deleting a unicast key. + */ +struct ieee80211req_del_key { + u_int8_t idk_keyix; /* key index */ + u_int8_t idk_macaddr[IEEE80211_ADDR_LEN]; +}; +/* + * MLME state manipulation request. IEEE80211_MLME_ASSOC + * only makes sense when operating as a station. The other + * requests can be used when operating as a station or an + * ap (to effect a station). + */ +struct ieee80211req_mlme { + u_int8_t im_op; /* operation to perform */ +#define IEEE80211_MLME_ASSOC 1 /* associate station */ +#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ +#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ +#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ +#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ + u_int16_t im_reason; /* 802.11 reason code */ + u_int8_t im_macaddr[IEEE80211_ADDR_LEN]; +}; + +struct ieee80211req_addpmkid { + u_int8_t pi_bssid[IEEE80211_ADDR_LEN]; + u_int8_t pi_enable; + u_int8_t pi_pmkid[16]; +}; + +#define AUTH_ALG_OPEN_SYSTEM 0x01 +#define AUTH_ALG_SHARED_KEY 0x02 +#define AUTH_ALG_LEAP 0x04 + +struct ieee80211req_authalg { + u_int8_t auth_alg; +}; + +/* + * Request to add an IE to a Management Frame + */ +enum{ + IEEE80211_APPIE_FRAME_BEACON = 0, + IEEE80211_APPIE_FRAME_PROBE_REQ = 1, + IEEE80211_APPIE_FRAME_PROBE_RESP = 2, + IEEE80211_APPIE_FRAME_ASSOC_REQ = 3, + IEEE80211_APPIE_FRAME_ASSOC_RESP = 4, + IEEE80211_APPIE_NUM_OF_FRAME = 5 +}; + +/* + * The Maximum length of the IE that can be added to a Management frame + */ +#define IEEE80211_APPIE_FRAME_MAX_LEN 200 + +struct ieee80211req_getset_appiebuf { + u_int32_t app_frmtype; /* management frame type for which buffer is added */ + u_int32_t app_buflen; /*application supplied buffer length */ + u_int8_t app_buf[]; +}; + +/* + * The following definitions are used by an application to set filter + * for receiving management frames + */ +enum { + IEEE80211_FILTER_TYPE_BEACON = 0x1, + IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2, + IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4, + IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8, + IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10, + IEEE80211_FILTER_TYPE_AUTH = 0x20, + IEEE80211_FILTER_TYPE_DEAUTH = 0x40, + IEEE80211_FILTER_TYPE_DISASSOC = 0x80, + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ +}; + +struct ieee80211req_set_filter { + u_int32_t app_filterype; /* management frame filter type */ +}; + +enum { + IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */ + IEEE80211_PARAM_MCASTCIPHER = 5, + IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */ + IEEE80211_PARAM_UCASTCIPHER = 8, + IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */ + IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */ + IEEE80211_PARAM_ROAMING = 12, /* roaming mode */ + IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */ + IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */ + IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */ + IEEE80211_PARAM_WAPI = 16, /* WAPI policy from wapid */ +}; + +/* + * Values for IEEE80211_PARAM_WPA + */ +#define WPA_MODE_WPA1 1 +#define WPA_MODE_WPA2 2 +#define WPA_MODE_AUTO 3 +#define WPA_MODE_NONE 4 + +struct ieee80211req_wpaie { + u_int8_t wpa_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t wpa_ie[IEEE80211_MAX_IE]; + u_int8_t rsn_ie[IEEE80211_MAX_IE]; +}; + +#ifndef IW_ENCODE_ALG_PMK +#define IW_ENCODE_ALG_PMK 4 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _IEEE80211_IOCTL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h new file mode 100644 index 000000000000..41f437307727 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h @@ -0,0 +1,339 @@ +//------------------------------------------------------------------------------ +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _OSAPI_LINUX_H_ +#define _OSAPI_LINUX_H_ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#ifndef INLINE +#define INLINE __inline +#endif +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +/* + * Endianes macros + */ +#define A_BE2CPU8(x) ntohb(x) +#define A_BE2CPU16(x) ntohs(x) +#define A_BE2CPU32(x) ntohl(x) + +#define A_LE2CPU8(x) (x) +#define A_LE2CPU16(x) (x) +#define A_LE2CPU32(x) (x) + +#define A_CPU2BE8(x) htonb(x) +#define A_CPU2BE16(x) htons(x) +#define A_CPU2BE32(x) htonl(x) + +#define A_MEMZERO(addr, len) memset(addr, 0, len) +#define A_MALLOC(size) kmalloc((size), GFP_KERNEL) +#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) + +#define A_LOGGER(mask, mod, args...) printk(KERN_ALERT args) +#define A_PRINTF(args...) printk(KERN_ALERT args) + +#define A_PRINTF_LOG(args...) printk(args) +#define A_SPRINTF(buf, args...) sprintf (buf, args) + +/* Mutual Exclusion */ +typedef spinlock_t A_MUTEX_T; +#define A_MUTEX_INIT(mutex) spin_lock_init(mutex) +#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) +#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) +#define A_IS_MUTEX_VALID(mutex) true /* okay to return true, since A_MUTEX_DELETE does nothing */ +#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */ + +/* Get current time in ms adding a constant offset (in ms) */ +#define A_GET_MS(offset) \ + (((jiffies / HZ) * 1000) + (offset)) + +/* + * Timer Functions + */ +#define A_MDELAY(msecs) mdelay(msecs) +typedef struct timer_list A_TIMER; + +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ + init_timer(pTimer); \ + (pTimer)->function = (pFunction); \ + (pTimer)->data = (unsigned long)(pArg); \ +} while (0) + +/* + * Start a Timer that elapses after 'periodMSec' milli-seconds + * Support is provided for a one-shot timer. The 'repeatFlag' is + * ignored. + */ +#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ + if (repeatFlag) { \ + printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ + panic("Timer Repeat"); \ + } \ + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ +} while (0) + +/* + * Cancel the Timer. + */ +#define A_UNTIMEOUT(pTimer) do { \ + del_timer((pTimer)); \ +} while (0) + +#define A_DELETE_TIMER(pTimer) do { \ +} while (0) + +/* + * Wait Queue related functions + */ +typedef wait_queue_head_t A_WAITQUEUE_HEAD; +#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif /* wait_event_interruptible_timeout */ + +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ + wait_event_interruptible_timeout(head, condition, timeout); \ +} while (0) + +#define A_WAKE_UP(head) wake_up(head) + +#ifdef DEBUG +extern unsigned int panic_on_assert; +#define A_ASSERT(expr) \ + if (!(expr)) { \ + printk(KERN_ALERT"Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \ + if (panic_on_assert) panic(#expr); \ + } +#else +#define A_ASSERT(expr) +#endif /* DEBUG */ + +#define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) request_firmware(_ppf, _pfile, _dev) +#define A_RELEASE_FIRMWARE(_pf) release_firmware(_pf) + +/* + * Initialization of the network buffer subsystem + */ +#define A_NETBUF_INIT() + +/* + * Network buffer queue support + */ +typedef struct sk_buff_head A_NETBUF_QUEUE_T; + +#define A_NETBUF_QUEUE_INIT(q) \ + a_netbuf_queue_init(q) + +#define A_NETBUF_ENQUEUE(q, pkt) \ + a_netbuf_enqueue((q), (pkt)) +#define A_NETBUF_PREQUEUE(q, pkt) \ + a_netbuf_prequeue((q), (pkt)) +#define A_NETBUF_DEQUEUE(q) \ + (a_netbuf_dequeue(q)) +#define A_NETBUF_QUEUE_SIZE(q) \ + a_netbuf_queue_size(q) +#define A_NETBUF_QUEUE_EMPTY(q) \ + (a_netbuf_queue_empty(q) ? true : false) + +/* + * Network buffer support + */ +#define A_NETBUF_ALLOC(size) \ + a_netbuf_alloc(size) +#define A_NETBUF_ALLOC_RAW(size) \ + a_netbuf_alloc_raw(size) +#define A_NETBUF_FREE(bufPtr) \ + a_netbuf_free(bufPtr) +#define A_NETBUF_DATA(bufPtr) \ + a_netbuf_to_data(bufPtr) +#define A_NETBUF_LEN(bufPtr) \ + a_netbuf_to_len(bufPtr) +#define A_NETBUF_PUSH(bufPtr, len) \ + a_netbuf_push(bufPtr, len) +#define A_NETBUF_PUT(bufPtr, len) \ + a_netbuf_put(bufPtr, len) +#define A_NETBUF_TRIM(bufPtr,len) \ + a_netbuf_trim(bufPtr, len) +#define A_NETBUF_PULL(bufPtr, len) \ + a_netbuf_pull(bufPtr, len) +#define A_NETBUF_HEADROOM(bufPtr)\ + a_netbuf_headroom(bufPtr) +#define A_NETBUF_SETLEN(bufPtr,len) \ + a_netbuf_setlen(bufPtr, len) + +/* Add data to end of a buffer */ +#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \ + a_netbuf_put_data(bufPtr, srcPtr, len) + +/* Add data to start of the buffer */ +#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \ + a_netbuf_push_data(bufPtr, srcPtr, len) + +/* Remove data at start of the buffer */ +#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \ + a_netbuf_pull_data(bufPtr, dstPtr, len) + +/* Remove data from the end of the buffer */ +#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \ + a_netbuf_trim_data(bufPtr, dstPtr, len) + +/* View data as "size" contiguous bytes of type "t" */ +#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \ + (t )( ((struct skbuf *)(bufPtr))->data) + +/* return the beginning of the headroom for the buffer */ +#define A_NETBUF_HEAD(bufPtr) \ + ((((struct sk_buff *)(bufPtr))->head)) + +/* + * OS specific network buffer access routines + */ +void *a_netbuf_alloc(int size); +void *a_netbuf_alloc_raw(int size); +void a_netbuf_free(void *bufPtr); +void *a_netbuf_to_data(void *bufPtr); +u32 a_netbuf_to_len(void *bufPtr); +int a_netbuf_push(void *bufPtr, s32 len); +int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len); +int a_netbuf_put(void *bufPtr, s32 len); +int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len); +int a_netbuf_pull(void *bufPtr, s32 len); +int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len); +int a_netbuf_trim(void *bufPtr, s32 len); +int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len); +int a_netbuf_setlen(void *bufPtr, s32 len); +s32 a_netbuf_headroom(void *bufPtr); +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt); +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt); +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); + +/* + * Kernel v.s User space functions + */ +u32 a_copy_to_user(void *to, const void *from, u32 n); +u32 a_copy_from_user(void *to, const void *from, u32 n); + +/* In linux, WLAN Rx and Tx run in different contexts, so no need to check + * for any commands/data queued for WLAN */ +#define A_CHECK_DRV_TX() + +#define A_GET_CACHE_LINE_BYTES() L1_CACHE_BYTES + +#define A_CACHE_LINE_PAD 128 + +static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) { + return (void *)L1_CACHE_ALIGN((unsigned long)ptr); +} + +#else /* __KERNEL__ */ + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#ifndef INLINE +#define INLINE __inline +#endif +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +#define A_MEMZERO(addr, len) memset((addr), 0, (len)) +#define A_MALLOC(size) malloc(size) + +#include + +#endif /* __KERNEL__ */ + +#endif /* _OSAPI_LINUX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h b/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h new file mode 100644 index 000000000000..c1fe0c6e4fa1 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the tunable configuration items for the WLAN module +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_WLAN_CONFIG_H_ +#define _HOST_WLAN_CONFIG_H_ + +/* Include definitions here that can be used to tune the WLAN module behavior. + * Different customers can tune the behavior as per their needs, here. + */ + +/* This configuration item when defined will consider the barker preamble + * mentioned in the ERP IE of the beacons from the AP to determine the short + * preamble support sent in the (Re)Assoc request frames. + */ +#define WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP 0 + +/* This config item when defined will not send the power module state transition + * failure events that happen during scan, to the host. + */ +#define WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN 0 + +/* + * This configuration item enable/disable keepalive support. + * Keepalive support: In the absence of any data traffic to AP, null + * frames will be sent to the AP at periodic interval, to keep the association + * active. This configuration item defines the periodic interval. + * Use value of zero to disable keepalive support + * Default: 60 seconds + */ +#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60 + +/* + * This configuration item sets the value of disconnect timeout + * Firmware delays sending the disconnec event to the host for this + * timeout after is gets disconnected from the current AP. + * If the firmware successly roams within the disconnect timeout + * it sends a new connect event + */ +#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 + +/* + * This configuration item disables 11n support. + * 0 - Enable + * 1 - Disable + */ +#define WLAN_CONFIG_DISABLE_11N 0 + +/* + * This configuration item enable BT clock sharing support + * 1 - Enable + * 0 - Disable (Default) + */ +#define WLAN_CONFIG_BT_SHARING 0 + +/* + * This configuration item sets WIFI OFF policy + * 0 - CUT_POWER + * 1 - DEEP_SLEEP (Default) + */ +#define WLAN_CONFIG_WLAN_OFF 1 + +/* + * This configuration item sets suspend policy + * 0 - CUT_POWER (Default) + * 1 - DEEP_SLEEP + * 2 - WoW + * 3 - CUT_POWER if BT OFF (clock sharing designs only) + */ +#define WLAN_CONFIG_PM_SUSPEND 0 + +/* + * This configuration item sets suspend policy to use if PM_SUSPEND is + * set to WoW and device is not connected at the time of suspend + * 0 - CUT_POWER (Default) + * 1 - DEEP_SLEEP + * 2 - WoW + * 3 - CUT_POWER if BT OFF (clock sharing designs only) + */ +#define WLAN_CONFIG_PM_WOW2 0 + +/* + * This configuration item enables/disables transmit bursting + * 0 - Enable tx Bursting (default) + * 1 - Disable tx bursting + */ +#define WLAN_CONFIG_DISABLE_TX_BURSTING 0 + +#endif /* _HOST_WLAN_CONFIG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h new file mode 100644 index 000000000000..1eb6f822d64e --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h @@ -0,0 +1,300 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _WMI_FILTER_LINUX_H_ +#define _WMI_FILTER_LINUX_H_ + +/* + * sioctl_filter - Standard ioctl + * pioctl_filter - Priv ioctl + * xioctl_filter - eXtended ioctl + * + * ---- Possible values for the WMI filter --------------- + * (0) - Block this cmd always (or) not implemented + * (INFRA_NETWORK) - Allow this cmd only in STA mode + * (ADHOC_NETWORK) - Allow this cmd only in IBSS mode + * (AP_NETWORK) - Allow this cmd only in AP mode + * (INFRA_NETWORK | ADHOC_NETWORK) - Block this cmd in AP mode + * (ADHOC_NETWORK | AP_NETWORK) - Block this cmd in STA mode + * (INFRA_NETWORK | AP_NETWORK) - Block this cmd in IBSS mode + * (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK)- allow only when mode is set + * (0xFF) - Allow this cmd always irrespective of mode + */ + +u8 sioctl_filter[] = { +(AP_NETWORK), /* SIOCSIWCOMMIT 0x8B00 */ +(0xFF), /* SIOCGIWNAME 0x8B01 */ +(0), /* SIOCSIWNWID 0x8B02 */ +(0), /* SIOCGIWNWID 0x8B03 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWFREQ 0x8B04 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWFREQ 0x8B05 */ +(0xFF), /* SIOCSIWMODE 0x8B06 */ +(0xFF), /* SIOCGIWMODE 0x8B07 */ +(0), /* SIOCSIWSENS 0x8B08 */ +(0), /* SIOCGIWSENS 0x8B09 */ +(0), /* SIOCSIWRANGE 0x8B0A */ +(0xFF), /* SIOCGIWRANGE 0x8B0B */ +(0), /* SIOCSIWPRIV 0x8B0C */ +(0), /* SIOCGIWPRIV 0x8B0D */ +(0), /* SIOCSIWSTATS 0x8B0E */ +(0), /* SIOCGIWSTATS 0x8B0F */ +(0), /* SIOCSIWSPY 0x8B10 */ +(0), /* SIOCGIWSPY 0x8B11 */ +(0), /* SIOCSIWTHRSPY 0x8B12 */ +(0), /* SIOCGIWTHRSPY 0x8B13 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWAP 0x8B14 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWAP 0x8B15 */ +#if (WIRELESS_EXT >= 18) +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWMLME 0X8B16 */ +#else +(0), /* Dummy 0 */ +#endif /* WIRELESS_EXT */ +(0), /* SIOCGIWAPLIST 0x8B17 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWSCAN 0x8B18 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWSCAN 0x8B19 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWESSID 0x8B1A */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWESSID 0x8B1B */ +(0), /* SIOCSIWNICKN 0x8B1C */ +(0), /* SIOCGIWNICKN 0x8B1D */ +(0), /* Dummy 0 */ +(0), /* Dummy 0 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWRATE 0x8B20 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWRATE 0x8B21 */ +(0), /* SIOCSIWRTS 0x8B22 */ +(0), /* SIOCGIWRTS 0x8B23 */ +(0), /* SIOCSIWFRAG 0x8B24 */ +(0), /* SIOCGIWFRAG 0x8B25 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWTXPOW 0x8B26 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWTXPOW 0x8B27 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWRETRY 0x8B28 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWRETRY 0x8B29 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWENCODE 0x8B2A */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWENCODE 0x8B2B */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWPOWER 0x8B2C */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWPOWER 0x8B2D */ +}; + + + +u8 pioctl_filter[] = { +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) */ +(AP_NETWORK), /* IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) */ +(INFRA_NETWORK), /* IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) */ +(0), /* IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) */ +(0), /* (SIOCIWFIRSTPRIV+6) */ +(0), /* (SIOCIWFIRSTPRIV+7) */ +(0), /* (SIOCIWFIRSTPRIV+8) */ +(0), /* (SIOCIWFIRSTPRIV+9) */ +(0), /* IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) */ +(0xFF), /* AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) */ +(INFRA_NETWORK), /* AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)*/ +(0xFF), /* AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) */ +(ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) */ +}; + + + +u8 xioctl_filter[] = { +(0xFF), /* Dummy 0 */ +(0xFF), /* AR6000_XIOCTL_BMI_DONE 1 */ +(0xFF), /* AR6000_XIOCTL_BMI_READ_MEMORY 2 */ +(0xFF), /* AR6000_XIOCTL_BMI_WRITE_MEMORY 3 */ +(0xFF), /* AR6000_XIOCTL_BMI_EXECUTE 4 */ +(0xFF), /* AR6000_XIOCTL_BMI_SET_APP_START 5 */ +(0xFF), /* AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 */ +(0xFF), /* AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 */ +(0xFF), /* AR6000_XIOCTL_BMI_TEST 8 */ +(0xFF), /* AR6000_XIOCTL_UNUSED9 9 */ +(0xFF), /* AR6000_XIOCTL_UNUSED10 10 */ +(0xFF), /* AR6000_XIOCTL_UNUSED11 11 */ +(0xFF), /* AR6000_XIOCTL_FORCE_TARGET_RESET 12 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_OPEN 13 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_CLOSE 14 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_READ 15 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_WRITE 16 */ +(0xFF), /* AR6000_XIOCTL_CHECK_TARGET_READY 17 */ +(0xFF), /* AR6000_XIOCTL_GPIO_OUTPUT_SET 18 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INPUT_GET 19 */ +(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_SET 20 */ +(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_GET 21 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INTR_ACK 22 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INTR_WAIT 23 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_ADHOC_BSSID 24 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_OPT_MODE 25 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_OPT_SEND_FRAME 26 */ +(ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_SET_BEACON_INTVAL 27 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETAUTHALG 28 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_MAX_SP 30 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 */ +(0xFF), /* AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 */ +(0xFF), /* AR6000_XIOCTL_TCMD_CONT_TX 38 */ +(0xFF), /* AR6000_XIOCTL_TCMD_CONT_RX 39 */ +(0xFF), /* AR6000_XIOCTL_TCMD_PM 40 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_STARTSCAN 41 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SETFIXRATES 42 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GETFIXRATES 43 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_CLR_RSSISNR 45 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_RTS 47 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_AUTHMODE 49 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WMM 51 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GET_RD 54 */ +(0xFF), /* AR6000_XIOCTL_DIAG_READ 55 */ +(0xFF), /* AR6000_XIOCTL_DIAG_WRITE 56 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_TXOP 57 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_USER_SETKEYS 58 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_APPIE 65 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 */ +(0xFF), /* AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 */ +(0xFF), /* AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 */ +(0xFF), /* Dummy 69 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_STATUS 71 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WOW_MODE 74 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_WOW_LIST 75 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 */ +(0xFF), /* AR6000_XIOCTL_TARGET_INFO 78 */ +(0xFF), /* AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 */ +(0xFF), /* AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 */ +(0xFF), /* Dummy 85 */ +(0xFF), /* Dummy 86 */ +(0xFF), /* Dummy 87 */ +(0xFF), /* Dummy 88 */ +(0xFF), /* Dummy 89 */ +(0xFF), /* AR6000_XIOCTL_UNUSED90 90 */ +(0xFF), /* AR6000_XIOCTL_BMI_LZ_STREAM_START 91 */ +(0xFF), /* AR6000_XIOCTL_BMI_LZ_DATA 92 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_CFG 93 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_ADDR_SET 94 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_START 95 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_STOP 96 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_COUNT_GET 97 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ABORT_SCAN 98 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STA_LIST 99 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_HIDDEN_SSID 100 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_NUM_STA 101 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_MAC 102 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_ACL_LIST 103 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_COMMIT_CONFIG 104 */ +(AP_NETWORK), /* IEEE80211_IOCTL_GETWPAIE 105 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_CONN_INACT_TIME 106 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 */ +(AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_COUNTRY 108 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_DTIM 109 */ +(0xFF), /* AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_IP 111 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_POLICY 112 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 */ +(0xFF), /* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 */ +(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 */ +(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 */ +(0xFF), /* AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 */ +(0xFF), /* AR6000_XIOCTL_SET_HT_CAP 118 */ +(0xFF), /* AR6000_XIOCTL_SET_HT_OP 119 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STAT 120 */ +(0xFF), /* AR6000_XIOCTL_SET_TX_SELECT_RATES 121 */ +(0xFF), /* AR6000_XIOCTL_SETUP_AGGR 122 */ +(0xFF), /* AR6000_XIOCTL_ALLOW_AGGR 123 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_COUNTRY 125 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_WMODE 126 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_DTIM 127 */ +(AP_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_AP_GET_BINTVL 128 */ +(0xFF), /* AR6000_XIOCTL_AP_GET_RTS 129 */ +(0xFF), /* AR6000_XIOCTL_DELE_AGGR 130 */ +(0xFF), /* AR6000_XIOCTL_FETCH_TARGET_REGS 131 */ +(0xFF), /* AR6000_XIOCTL_HCI_CMD 132 */ +(0xFF), /* AR6000_XIOCTL_ACL_DATA(used to be used for PAL) 133 */ +(0xFF), /* AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_11BG_RATESET 135 */ +(0xFF), +(0xFF), +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_GET_STATS 147 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 */ +(0xFF), /* AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 */ +(0xFF), /* AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 */ +(0xFF), /* AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 */ +(0xFF), /* AR6000_XIOCTL_ADD_AP_INTERFACE 152 */ +(0xFF), /* AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE 155 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PASSPHRASE 156 */ +(0xFF), +(0xFF), +(0xFF), +(0xFF), +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 */ +}; + +#endif /*_WMI_FILTER_LINUX_H_*/ diff --git a/trunk/drivers/staging/ath6kl/os/linux/netbuf.c b/trunk/drivers/staging/ath6kl/os/linux/netbuf.c new file mode 100644 index 000000000000..963a2fb76a92 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/netbuf.c @@ -0,0 +1,231 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ +#include +#include "athdefs.h" +#include "a_osapi.h" +#include "htc_packet.h" + +#define AR6000_DATA_OFFSET 64 + +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt) +{ + skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt); +} + +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt) +{ + skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt); +} + +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q) +{ + return((void *) skb_dequeue((struct sk_buff_head *) q)); +} + +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q) +{ + return(skb_queue_len((struct sk_buff_head *) q)); +} + +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q) +{ + return(skb_queue_empty((struct sk_buff_head *) q)); +} + +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q) +{ + skb_queue_head_init((struct sk_buff_head *) q); +} + +void * +a_netbuf_alloc(int size) +{ + struct sk_buff *skb; + size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */ + skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size); + skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES()); + return ((void *)skb); +} + +/* + * Allocate an SKB w.o. any encapsulation requirement. + */ +void * +a_netbuf_alloc_raw(int size) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb(size); + + return ((void *)skb); +} + +void +a_netbuf_free(void *bufPtr) +{ + struct sk_buff *skb = (struct sk_buff *)bufPtr; + + dev_kfree_skb(skb); +} + +u32 a_netbuf_to_len(void *bufPtr) +{ + return (((struct sk_buff *)bufPtr)->len); +} + +void * +a_netbuf_to_data(void *bufPtr) +{ + return (((struct sk_buff *)bufPtr)->data); +} + +/* + * Add len # of bytes to the beginning of the network buffer + * pointed to by bufPtr + */ +int +a_netbuf_push(void *bufPtr, s32 len) +{ + skb_push((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the beginning of the network buffer + * pointed to by bufPtr and also fill with data + */ +int +a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len) +{ + skb_push((struct sk_buff *) bufPtr, len); + memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the end of the network buffer + * pointed to by bufPtr + */ +int +a_netbuf_put(void *bufPtr, s32 len) +{ + skb_put((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the end of the network buffer + * pointed to by bufPtr and also fill with data + */ +int +a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len) +{ + char *start = (char*)(((struct sk_buff *)bufPtr)->data + + ((struct sk_buff *)bufPtr)->len); + skb_put((struct sk_buff *)bufPtr, len); + memcpy(start, srcPtr, len); + + return 0; +} + + +/* + * Trim the network buffer pointed to by bufPtr to len # of bytes + */ +int +a_netbuf_setlen(void *bufPtr, s32 len) +{ + skb_trim((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Chop of len # of bytes from the end of the buffer. + */ +int +a_netbuf_trim(void *bufPtr, s32 len) +{ + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); + + return 0; +} + +/* + * Chop of len # of bytes from the end of the buffer and return the data. + */ +int +a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len) +{ + char *start = (char*)(((struct sk_buff *)bufPtr)->data + + (((struct sk_buff *)bufPtr)->len - len)); + + memcpy(dstPtr, start, len); + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); + + return 0; +} + + +/* + * Returns the number of bytes available to a a_netbuf_push() + */ +s32 a_netbuf_headroom(void *bufPtr) +{ + return (skb_headroom((struct sk_buff *)bufPtr)); +} + +/* + * Removes specified number of bytes from the beginning of the buffer + */ +int +a_netbuf_pull(void *bufPtr, s32 len) +{ + skb_pull((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Removes specified number of bytes from the beginning of the buffer + * and return the data + */ +int +a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len) +{ + memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len); + skb_pull((struct sk_buff *)bufPtr, len); + + return 0; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +EXPORT_SYMBOL(a_netbuf_to_data); +EXPORT_SYMBOL(a_netbuf_put); +EXPORT_SYMBOL(a_netbuf_pull); +EXPORT_SYMBOL(a_netbuf_alloc); +EXPORT_SYMBOL(a_netbuf_free); +#endif diff --git a/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h b/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h new file mode 100644 index 000000000000..11125967d53d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +#ifndef __AGGR_RX_INTERNAL_H__ +#define __AGGR_RX_INTERNAL_H__ + +#include "a_osapi.h" +#include "aggr_recv_api.h" + +#define AGGR_WIN_IDX(x, y) ((x) % (y)) +#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x)+1), (y)) +#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x)-1), (y)) +#define IEEE80211_MAX_SEQ_NO 0xFFF +#define IEEE80211_NEXT_SEQ_NO(x) (((x) + 1) & IEEE80211_MAX_SEQ_NO) + + +#define NUM_OF_TIDS 8 +#define AGGR_SZ_DEFAULT 8 + +#define AGGR_WIN_SZ_MIN 2 +#define AGGR_WIN_SZ_MAX 8 +/* TID Window sz is double of what is negotiated. Derive TID_WINDOW_SZ from win_sz, per tid */ +#define TID_WINDOW_SZ(_x) ((_x) << 1) + +#define AGGR_NUM_OF_FREE_NETBUFS 16 + +#define AGGR_GET_RXTID_STATS(_p, _x) (&(_p->stat[(_x)])) +#define AGGR_GET_RXTID(_p, _x) (&(_p->RxTid[(_x)])) + +/* Hold q is a function of win_sz, which is negotiated per tid */ +#define HOLD_Q_SZ(_x) (TID_WINDOW_SZ((_x))*sizeof(struct osbuf_hold_q)) +/* AGGR_RX_TIMEOUT value is important as a (too) small value can cause frames to be + * delivered out of order and a (too) large value can cause undesirable latency in + * certain situations. */ +#define AGGR_RX_TIMEOUT 400 /* Timeout(in ms) for delivery of frames, if they are stuck */ + +typedef enum { + ALL_SEQNO = 0, + CONTIGUOUS_SEQNO = 1, +}DELIVERY_ORDER; + +struct osbuf_hold_q { + void *osbuf; + bool is_amsdu; + u16 seq_no; +}; + + +#if 0 +/* XXX: unused ? */ +struct window_snapshot { + u16 seqno_st; + u16 seqno_end; +}; +#endif + +struct rxtid { + bool aggr; /* is it ON or OFF */ + bool progress; /* true when frames have arrived after a timer start */ + bool timerMon; /* true if the timer started for the sake of this TID */ + u16 win_sz; /* negotiated window size */ + u16 seq_next; /* Next seq no, in current window */ + u32 hold_q_sz; /* Num of frames that can be held in hold q */ + struct osbuf_hold_q *hold_q; /* Hold q for re-order */ +#if 0 + struct window_snapshot old_win; /* Sliding window snapshot - for timeout */ +#endif + A_NETBUF_QUEUE_T q; /* q head for enqueuing frames for dispatch */ + A_MUTEX_T lock; +}; + +struct rxtid_stats { + u32 num_into_aggr; /* hitting at the input of this module */ + u32 num_dups; /* duplicate */ + u32 num_oow; /* out of window */ + u32 num_mpdu; /* single payload 802.3/802.11 frame */ + u32 num_amsdu; /* AMSDU */ + u32 num_delivered; /* frames delivered to IP stack */ + u32 num_timeouts; /* num of timeouts, during which frames delivered */ + u32 num_hole; /* frame not present, when window moved over */ + u32 num_bar; /* num of resets of seq_num, via BAR */ +}; + +struct aggr_info { + u8 aggr_sz; /* config value of aggregation size */ + u8 timerScheduled; + A_TIMER timer; /* timer for returning held up pkts in re-order que */ + void *dev; /* dev handle */ + RX_CALLBACK rx_fn; /* callback function to return frames; to upper layer */ + struct rxtid RxTid[NUM_OF_TIDS]; /* Per tid window */ + ALLOC_NETBUFS netbuf_allocator; /* OS netbuf alloc fn */ + A_NETBUF_QUEUE_T freeQ; /* pre-allocated buffers - for A_MSDU slicing */ + struct rxtid_stats stat[NUM_OF_TIDS]; /* Tid based statistics */ + PACKET_LOG pkt_log; /* Log info of the packets */ +}; + +#endif /* __AGGR_RX_INTERNAL_H__ */ diff --git a/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c b/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c new file mode 100644 index 000000000000..9b1509ec5a7b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c @@ -0,0 +1,661 @@ +/* + * + * Copyright (c) 2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +#include +#include +#include +#include +#include "pkt_log.h" +#include "aggr_recv_api.h" +#include "aggr_rx_internal.h" +#include "wmi.h" + +extern int +wmi_dot3_2_dix(void *osbuf); + +static void +aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf); + +static void +aggr_timeout(unsigned long arg); + +static void +aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order); + +static void +aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q); + +static void * +aggr_get_osbuf(struct aggr_info *p_aggr); + +void * +aggr_init(ALLOC_NETBUFS netbuf_allocator) +{ + struct aggr_info *p_aggr = NULL; + struct rxtid *rxtid; + u8 i; + int status = 0; + + A_PRINTF("In aggr_init..\n"); + + do { + p_aggr = A_MALLOC(sizeof(struct aggr_info)); + if(!p_aggr) { + A_PRINTF("Failed to allocate memory for aggr_node\n"); + status = A_ERROR; + break; + } + + /* Init timer and data structures */ + A_MEMZERO(p_aggr, sizeof(struct aggr_info)); + p_aggr->aggr_sz = AGGR_SZ_DEFAULT; + A_INIT_TIMER(&p_aggr->timer, aggr_timeout, p_aggr); + p_aggr->timerScheduled = false; + A_NETBUF_QUEUE_INIT(&p_aggr->freeQ); + + p_aggr->netbuf_allocator = netbuf_allocator; + p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS); + + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timerMon = false; + A_NETBUF_QUEUE_INIT(&rxtid->q); + A_MUTEX_INIT(&rxtid->lock); + } + }while(false); + + A_PRINTF("going out of aggr_init..status %s\n", + (status == 0) ? "OK":"Error"); + + if (status) { + /* Cleanup */ + aggr_module_destroy(p_aggr); + } + return ((status == 0) ? p_aggr : NULL); +} + +/* utility function to clear rx hold_q for a tid */ +static void +aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) +{ + struct rxtid *rxtid; + struct rxtid_stats *stats; + + A_ASSERT(tid < NUM_OF_TIDS && p_aggr); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + if(rxtid->aggr) { + aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO); + } + + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timerMon = false; + rxtid->win_sz = 0; + rxtid->seq_next = 0; + rxtid->hold_q_sz = 0; + + if(rxtid->hold_q) { + kfree(rxtid->hold_q); + rxtid->hold_q = NULL; + } + + A_MEMZERO(stats, sizeof(struct rxtid_stats)); +} + +void +aggr_module_destroy(void *cntxt) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + u8 i, k; + A_PRINTF("%s(): aggr = %p\n",_A_FUNCNAME_, p_aggr); + A_ASSERT(p_aggr); + + if(p_aggr) { + if(p_aggr->timerScheduled) { + A_UNTIMEOUT(&p_aggr->timer); + p_aggr->timerScheduled = false; + } + + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + /* Free the hold q contents and hold_q*/ + if(rxtid->hold_q) { + for(k = 0; k< rxtid->hold_q_sz; k++) { + if(rxtid->hold_q[k].osbuf) { + A_NETBUF_FREE(rxtid->hold_q[k].osbuf); + } + } + kfree(rxtid->hold_q); + } + /* Free the dispatch q contents*/ + while(A_NETBUF_QUEUE_SIZE(&rxtid->q)) { + A_NETBUF_FREE(A_NETBUF_DEQUEUE(&rxtid->q)); + } + if (A_IS_MUTEX_VALID(&rxtid->lock)) { + A_MUTEX_DELETE(&rxtid->lock); + } + } + /* free the freeQ and its contents*/ + while(A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) { + A_NETBUF_FREE(A_NETBUF_DEQUEUE(&p_aggr->freeQ)); + } + kfree(p_aggr); + } + A_PRINTF("out aggr_module_destroy\n"); +} + + +void +aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + + A_ASSERT(p_aggr && fn && dev); + + p_aggr->rx_fn = fn; + p_aggr->dev = dev; +} + + +void +aggr_process_bar(void *cntxt, u8 tid, u16 seq_no) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + stats->num_bar++; + + aggr_deque_frms(p_aggr, tid, seq_no, ALL_SEQNO); +} + + +void +aggr_recv_addba_req_evt(void *cntxt, u8 tid, u16 seq_no, u8 win_sz) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + A_PRINTF("%s(): win_sz = %d aggr %d\n", _A_FUNCNAME_, win_sz, rxtid->aggr); + if(win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) { + A_PRINTF("win_sz %d, tid %d\n", win_sz, tid); + } + + if(rxtid->aggr) { + /* Just go and deliver all the frames up from this + * queue, as if we got DELBA and re-initialize the queue + */ + aggr_delete_tid_state(p_aggr, tid); + } + + rxtid->seq_next = seq_no; + /* create these queues, only upon receiving of ADDBA for a + * tid, reducing memory requirement + */ + rxtid->hold_q = A_MALLOC(HOLD_Q_SZ(win_sz)); + if((rxtid->hold_q == NULL)) { + A_PRINTF("Failed to allocate memory, tid = %d\n", tid); + A_ASSERT(0); + } + A_MEMZERO(rxtid->hold_q, HOLD_Q_SZ(win_sz)); + + /* Update rxtid for the window sz */ + rxtid->win_sz = win_sz; + /* hold_q_sz inicates the depth of holding q - which is + * a factor of win_sz. Compute once, as it will be used often + */ + rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz); + /* There should be no frames on q - even when second ADDBA comes in. + * If aggr was previously ON on this tid, we would have cleaned up + * the q + */ + if(A_NETBUF_QUEUE_SIZE(&rxtid->q) != 0) { + A_PRINTF("ERROR: Frames still on queue ?\n"); + A_ASSERT(0); + } + + rxtid->aggr = true; +} + +void +aggr_recv_delba_req_evt(void *cntxt, u8 tid) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + + A_ASSERT(p_aggr); + A_PRINTF("%s(): tid %d\n", _A_FUNCNAME_, tid); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + + if(rxtid->aggr) { + aggr_delete_tid_state(p_aggr, tid); + } +} + +static void +aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order) +{ + struct rxtid *rxtid; + struct osbuf_hold_q *node; + u16 idx, idx_end, seq_end; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + /* idx is absolute location for first frame */ + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + + /* idx_end is typically the last possible frame in the window, + * but changes to 'the' seq_no, when BAR comes. If seq_no + * is non-zero, we will go up to that and stop. + * Note: last seq no in current window will occupy the same + * index position as index that is just previous to start. + * An imp point : if win_sz is 7, for seq_no space of 4095, + * then, there would be holes when sequence wrap around occurs. + * Target should judiciously choose the win_sz, based on + * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz + * 2, 4, 8, 16 win_sz works fine). + * We must deque from "idx" to "idx_end", including both. + */ + seq_end = (seq_no) ? seq_no : rxtid->seq_next; + idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); + + /* Critical section begins */ + A_MUTEX_LOCK(&rxtid->lock); + do { + + node = &rxtid->hold_q[idx]; + + if((order == CONTIGUOUS_SEQNO) && (!node->osbuf)) + break; + + /* chain frames and deliver frames bcos: + * 1. either the frames are in order and window is contiguous, OR + * 2. we need to deque frames, irrespective of holes + */ + if(node->osbuf) { + if(node->is_amsdu) { + aggr_slice_amsdu(p_aggr, rxtid, &node->osbuf); + } else { + A_NETBUF_ENQUEUE(&rxtid->q, node->osbuf); + } + node->osbuf = NULL; + } else { + stats->num_hole++; + } + + /* window is moving */ + rxtid->seq_next = IEEE80211_NEXT_SEQ_NO(rxtid->seq_next); + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + } while(idx != idx_end); + /* Critical section ends */ + A_MUTEX_UNLOCK(&rxtid->lock); + + stats->num_delivered += A_NETBUF_QUEUE_SIZE(&rxtid->q); + aggr_dispatch_frames(p_aggr, &rxtid->q); +} + +static void * +aggr_get_osbuf(struct aggr_info *p_aggr) +{ + void *buf = NULL; + + /* Starving for buffers? get more from OS + * check for low netbuffers( < 1/4 AGGR_NUM_OF_FREE_NETBUFS) : + * re-allocate bufs if so + * allocate a free buf from freeQ + */ + if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) { + p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS); + } + + if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) { + buf = A_NETBUF_DEQUEUE(&p_aggr->freeQ); + } + + return buf; +} + + +static void +aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf) +{ + void *new_buf; + u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len; + u8 *framep; + + /* Frame format at this point: + * [DIX hdr | 802.3 | 802.3 | ... | 802.3] + * + * Strip the DIX header. + * Iterate through the osbuf and do: + * grab a free netbuf from freeQ + * find the start and end of a frame + * copy it to netbuf(Vista can do better here) + * convert all msdu's(802.3) frames to upper layer format - os routine + * -for now lets convert from 802.3 to dix + * enque this to dispatch q of tid + * repeat + * free the osbuf - to OS. It's been sliced. + */ + + mac_hdr_len = sizeof(ATH_MAC_HDR); + framep = A_NETBUF_DATA(*osbuf) + mac_hdr_len; + amsdu_len = A_NETBUF_LEN(*osbuf) - mac_hdr_len; + + while(amsdu_len > mac_hdr_len) { + /* Begin of a 802.3 frame */ + payload_8023_len = A_BE2CPU16(((ATH_MAC_HDR *)framep)->typeOrLen); +#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508 +#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46 + if(payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN || payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) { + A_PRINTF("802.3 AMSDU frame bound check failed. len %d\n", payload_8023_len); + break; + } + frame_8023_len = payload_8023_len + mac_hdr_len; + new_buf = aggr_get_osbuf(p_aggr); + if(new_buf == NULL) { + A_PRINTF("No buffer available \n"); + break; + } + + memcpy(A_NETBUF_DATA(new_buf), framep, frame_8023_len); + A_NETBUF_PUT(new_buf, frame_8023_len); + if (wmi_dot3_2_dix(new_buf) != 0) { + A_PRINTF("dot3_2_dix err..\n"); + A_NETBUF_FREE(new_buf); + break; + } + + A_NETBUF_ENQUEUE(&rxtid->q, new_buf); + + /* Is this the last subframe within this aggregate ? */ + if ((amsdu_len - frame_8023_len) == 0) { + break; + } + + /* Add the length of A-MSDU subframe padding bytes - + * Round to nearest word. + */ + frame_8023_len = ((frame_8023_len + 3) & ~3); + + framep += frame_8023_len; + amsdu_len -= frame_8023_len; + } + + A_NETBUF_FREE(*osbuf); + *osbuf = NULL; +} + +void +aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + u16 idx, st, cur, end; + u16 *log_idx; + struct osbuf_hold_q *node; + PACKET_LOG *log; + + A_ASSERT(p_aggr); + A_ASSERT(tid < NUM_OF_TIDS); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + stats->num_into_aggr++; + + if(!rxtid->aggr) { + if(is_amsdu) { + aggr_slice_amsdu(p_aggr, rxtid, osbuf); + stats->num_amsdu++; + aggr_dispatch_frames(p_aggr, &rxtid->q); + } + return; + } + + /* Check the incoming sequence no, if it's in the window */ + st = rxtid->seq_next; + cur = seq_no; + end = (st + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO; + /* Log the pkt info for future analysis */ + log = &p_aggr->pkt_log; + log_idx = &log->last_idx; + log->info[*log_idx].cur = cur; + log->info[*log_idx].st = st; + log->info[*log_idx].end = end; + *log_idx = IEEE80211_NEXT_SEQ_NO(*log_idx); + + if(((st < end) && (cur < st || cur > end)) || + ((st > end) && (cur > end) && (cur < st))) { + /* the cur frame is outside the window. Since we know + * our target would not do this without reason it must + * be assumed that the window has moved for some valid reason. + * Therefore, we dequeue all frames and start fresh. + */ + u16 extended_end; + + extended_end = (end + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO; + + if(((end < extended_end) && (cur < end || cur > extended_end)) || + ((end > extended_end) && (cur > extended_end) && (cur < end))) { + // dequeue all frames in queue and shift window to new frame + aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO); + //set window start so that new frame is last frame in window + if(cur >= rxtid->hold_q_sz-1) { + rxtid->seq_next = cur - (rxtid->hold_q_sz-1); + }else{ + rxtid->seq_next = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur); + } + } else { + // dequeue only those frames that are outside the new shifted window + if(cur >= rxtid->hold_q_sz-1) { + st = cur - (rxtid->hold_q_sz-1); + }else{ + st = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur); + } + + aggr_deque_frms(p_aggr, tid, st, ALL_SEQNO); + } + + stats->num_oow++; + } + + idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz); + + /*enque the frame, in hold_q */ + node = &rxtid->hold_q[idx]; + + A_MUTEX_LOCK(&rxtid->lock); + if(node->osbuf) { + /* Is the cur frame duplicate or something beyond our + * window(hold_q -> which is 2x, already)? + * 1. Duplicate is easy - drop incoming frame. + * 2. Not falling in current sliding window. + * 2a. is the frame_seq_no preceding current tid_seq_no? + * -> drop the frame. perhaps sender did not get our ACK. + * this is taken care of above. + * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ); + * -> Taken care of it above, by moving window forward. + * + */ + A_NETBUF_FREE(node->osbuf); + stats->num_dups++; + } + + node->osbuf = *osbuf; + node->is_amsdu = is_amsdu; + node->seq_no = seq_no; + if(node->is_amsdu) { + stats->num_amsdu++; + } else { + stats->num_mpdu++; + } + A_MUTEX_UNLOCK(&rxtid->lock); + + *osbuf = NULL; + aggr_deque_frms(p_aggr, tid, 0, CONTIGUOUS_SEQNO); + + if(p_aggr->timerScheduled) { + rxtid->progress = true; + }else{ + for(idx=0 ; idxhold_q_sz ; idx++) { + if(rxtid->hold_q[idx].osbuf) { + /* there is a frame in the queue and no timer so + * start a timer to ensure that the frame doesn't remain + * stuck forever. */ + p_aggr->timerScheduled = true; + A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0); + rxtid->progress = false; + rxtid->timerMon = true; + break; + } + } + } +} + +/* + * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate + * hold Q state. Examples include when a Connect event or disconnect event is + * received. + */ +void +aggr_reset_state(void *cntxt) +{ + u8 tid; + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + + A_ASSERT(p_aggr); + + for(tid=0 ; tidaggr == false || + rxtid->timerMon == false || + rxtid->progress == true) { + continue; + } + // dequeue all frames in for this tid + stats->num_timeouts++; + A_PRINTF("TO: st %d end %d\n", rxtid->seq_next, ((rxtid->seq_next + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO)); + aggr_deque_frms(p_aggr, i, 0, ALL_SEQNO); + } + + p_aggr->timerScheduled = false; + // determine whether a new timer should be started. + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + + if(rxtid->aggr == true && rxtid->hold_q) { + for(j = 0 ; j < rxtid->hold_q_sz ; j++) + { + if(rxtid->hold_q[j].osbuf) + { + p_aggr->timerScheduled = true; + rxtid->timerMon = true; + rxtid->progress = false; + break; + } + } + + if(j >= rxtid->hold_q_sz) { + rxtid->timerMon = false; + } + } + } + + if(p_aggr->timerScheduled) { + /* Rearm the timer*/ + A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0); + } + +} + +static void +aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q) +{ + void *osbuf; + + while((osbuf = A_NETBUF_DEQUEUE(q))) { + p_aggr->rx_fn(p_aggr->dev, osbuf); + } +} + +void +aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + u8 i; + + *log_buf = &p_aggr->pkt_log; + A_PRINTF("\n\n================================================\n"); + A_PRINTF("tid: num_into_aggr, dups, oow, mpdu, amsdu, delivered, timeouts, holes, bar, seq_next\n"); + for(i = 0; i < NUM_OF_TIDS; i++) { + stats = AGGR_GET_RXTID_STATS(p_aggr, i); + rxtid = AGGR_GET_RXTID(p_aggr, i); + A_PRINTF("%d: %d %d %d %d %d %d %d %d %d : %d\n", i, stats->num_into_aggr, stats->num_dups, + stats->num_oow, stats->num_mpdu, + stats->num_amsdu, stats->num_delivered, stats->num_timeouts, + stats->num_hole, stats->num_bar, + rxtid->seq_next); + } + A_PRINTF("================================================\n\n"); + +} diff --git a/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h new file mode 100644 index 000000000000..cf47d0657e70 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h @@ -0,0 +1,397 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _NET80211_IEEE80211_H_ +#define _NET80211_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ +#define IEEE80211_WEP_KEYLEN 5 /* 40bit */ +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ +#define IEEE80211_WEP_NKID 4 /* number of key ids */ + +/* + * 802.11i defines an extended IV for use with non-WEP ciphers. + * When the EXTIV bit is set in the key id byte an additional + * 4 bytes immediately follow the IV for TKIP. For CCMP the + * EXTIV bit is likewise set but the 8 bytes represent the + * CCMP header rather than IV+extended-IV. + */ +#define IEEE80211_WEP_EXTIV 0x20 +#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */ +#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */ + +#define IEEE80211_CRC_LEN 4 + +#ifdef WAPI_ENABLE +#define IEEE80211_WAPI_EXTIVLEN 10 /* extended IV length */ +#endif /* WAPI ENABLE */ + + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) +#define IEEE80211_IS_BROADCAST(_a) (*(_a) == 0xFF) +#define WEP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) +#define WEP_TRAILER IEEE80211_WEP_CRCLEN +#define CCMP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_EXTIVLEN) +#define CCMP_TRAILER IEEE80211_WEP_MICLEN +#define TKIP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_EXTIVLEN) +#define TKIP_TRAILER IEEE80211_WEP_CRCLEN +#define TKIP_MICLEN IEEE80211_WEP_MICLEN + + +#define IEEE80211_ADDR_EQ(addr1, addr2) \ + (memcmp(addr1, addr2, IEEE80211_ADDR_LEN) == 0) + +#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN) + +#define IEEE80211_KEYBUF_SIZE 16 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */ + +/* + * NB: these values are ordered carefully; there are lots of + * of implications in any reordering. In particular beware + * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY. + */ +#define IEEE80211_CIPHER_WEP 0 +#define IEEE80211_CIPHER_TKIP 1 +#define IEEE80211_CIPHER_AES_OCB 2 +#define IEEE80211_CIPHER_AES_CCM 3 +#define IEEE80211_CIPHER_CKIP 5 +#define IEEE80211_CIPHER_CCKM_KRK 6 +#define IEEE80211_CIPHER_NONE 7 /* pseudo value */ + +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) + +#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \ + (((len) == 5) || ((len) == 13) || ((len) == 16)) + + + +/* + * generic definitions for IEEE 802.11 frames + */ +PREPACK struct ieee80211_frame { + u8 i_fc[2]; + u8 i_dur[2]; + u8 i_addr1[IEEE80211_ADDR_LEN]; + u8 i_addr2[IEEE80211_ADDR_LEN]; + u8 i_addr3[IEEE80211_ADDR_LEN]; + u8 i_seq[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} POSTPACK; + +PREPACK struct ieee80211_qosframe { + u8 i_fc[2]; + u8 i_dur[2]; + u8 i_addr1[IEEE80211_ADDR_LEN]; + u8 i_addr2[IEEE80211_ADDR_LEN]; + u8 i_addr3[IEEE80211_ADDR_LEN]; + u8 i_seq[2]; + u8 i_qos[2]; +} POSTPACK; + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +/* for TYPE_CTL */ +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_CFACK 0x50 +#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60 +#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_WEP 0x40 +#define IEEE80211_FC1_ORDER 0x80 + +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 + +#define IEEE80211_NWID_LEN 32 + +/* + * 802.11 rate set. + */ +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */ + +#define WMM_NUM_AC 4 /* 4 AC categories */ + +#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */ +#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */ +#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */ +#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */ +#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */ +#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */ +#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */ +#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */ + +#define WMM_AC_TO_TID(_ac) ( \ + ((_ac) == WMM_AC_VO) ? 6 : \ + ((_ac) == WMM_AC_VI) ? 5 : \ + ((_ac) == WMM_AC_BK) ? 1 : \ + 0) + +#define TID_TO_WMM_AC(_tid) ( \ + ((_tid) < 1) ? WMM_AC_BE : \ + ((_tid) < 3) ? WMM_AC_BK : \ + ((_tid) < 6) ? WMM_AC_VI : \ + WMM_AC_VO) +/* + * Management information element payloads. + */ + +enum { + IEEE80211_ELEMID_SSID = 0, + IEEE80211_ELEMID_RATES = 1, + IEEE80211_ELEMID_FHPARMS = 2, + IEEE80211_ELEMID_DSPARMS = 3, + IEEE80211_ELEMID_CFPARMS = 4, + IEEE80211_ELEMID_TIM = 5, + IEEE80211_ELEMID_IBSSPARMS = 6, + IEEE80211_ELEMID_COUNTRY = 7, + IEEE80211_ELEMID_CHALLENGE = 16, + /* 17-31 reserved for challenge text extension */ + IEEE80211_ELEMID_PWRCNSTR = 32, + IEEE80211_ELEMID_PWRCAP = 33, + IEEE80211_ELEMID_TPCREQ = 34, + IEEE80211_ELEMID_TPCREP = 35, + IEEE80211_ELEMID_SUPPCHAN = 36, + IEEE80211_ELEMID_CHANSWITCH = 37, + IEEE80211_ELEMID_MEASREQ = 38, + IEEE80211_ELEMID_MEASREP = 39, + IEEE80211_ELEMID_QUIET = 40, + IEEE80211_ELEMID_IBSSDFS = 41, + IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_HTCAP_ANA = 45, /* Address ANA, and non-ANA story, for interop. CL#171733 */ + IEEE80211_ELEMID_RSN = 48, + IEEE80211_ELEMID_XRATES = 50, + IEEE80211_ELEMID_HTINFO_ANA = 61, +#ifdef WAPI_ENABLE + IEEE80211_ELEMID_WAPI = 68, +#endif + IEEE80211_ELEMID_TPC = 150, + IEEE80211_ELEMID_CCKM = 156, + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ +}; + +#define ATH_OUI 0x7f0300 /* Atheros OUI */ +#define ATH_OUI_TYPE 0x01 +#define ATH_OUI_SUBTYPE 0x01 +#define ATH_OUI_VERSION 0x00 + +#define WPA_OUI 0xf25000 +#define WPA_OUI_TYPE 0x01 +#define WPA_VERSION 1 /* current supported version */ + +#define WPA_CSE_NULL 0x00 +#define WPA_CSE_WEP40 0x01 +#define WPA_CSE_TKIP 0x02 +#define WPA_CSE_CCMP 0x04 +#define WPA_CSE_WEP104 0x05 + +#define WPA_ASE_NONE 0x00 +#define WPA_ASE_8021X_UNSPEC 0x01 +#define WPA_ASE_8021X_PSK 0x02 + +#define RSN_OUI 0xac0f00 +#define RSN_VERSION 1 /* current supported version */ + +#define RSN_CSE_NULL 0x00 +#define RSN_CSE_WEP40 0x01 +#define RSN_CSE_TKIP 0x02 +#define RSN_CSE_WRAP 0x03 +#define RSN_CSE_CCMP 0x04 +#define RSN_CSE_WEP104 0x05 + +#define RSN_ASE_NONE 0x00 +#define RSN_ASE_8021X_UNSPEC 0x01 +#define RSN_ASE_8021X_PSK 0x02 + +#define RSN_CAP_PREAUTH 0x01 + +#define WMM_OUI 0xf25000 +#define WMM_OUI_TYPE 0x02 +#define WMM_INFO_OUI_SUBTYPE 0x00 +#define WMM_PARAM_OUI_SUBTYPE 0x01 +#define WMM_VERSION 1 + +/* WMM stream classes */ +#define WMM_NUM_AC 4 +#define WMM_AC_BE 0 /* best effort */ +#define WMM_AC_BK 1 /* background */ +#define WMM_AC_VI 2 /* video */ +#define WMM_AC_VO 3 /* voice */ + +/* TSPEC related */ +#define ACTION_CATEGORY_CODE_TSPEC 17 +#define ACTION_CODE_TSPEC_ADDTS 0 +#define ACTION_CODE_TSPEC_ADDTS_RESP 1 +#define ACTION_CODE_TSPEC_DELTS 2 + +typedef enum { + TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0, + TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1, + TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3, + TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8, + TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9, + TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA, + TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB, + TSPEC_STATUS_CODE_DELTS_SENT = 0x30, + TSPEC_STATUS_CODE_DELTS_RECV = 0x31, +} TSPEC_STATUS_CODE; + +#define TSPEC_TSID_MASK 0xF +#define TSPEC_TSID_S 1 + +/* + * WMM/802.11e Tspec Element + */ +typedef PREPACK struct wmm_tspec_ie_t { + u8 elementId; + u8 len; + u8 oui[3]; + u8 ouiType; + u8 ouiSubType; + u8 version; + u16 tsInfo_info; + u8 tsInfo_reserved; + u16 nominalMSDU; + u16 maxMSDU; + u32 minServiceInt; + u32 maxServiceInt; + u32 inactivityInt; + u32 suspensionInt; + u32 serviceStartTime; + u32 minDataRate; + u32 meanDataRate; + u32 peakDataRate; + u32 maxBurstSize; + u32 delayBound; + u32 minPhyRate; + u16 sba; + u16 mediumTime; +} POSTPACK WMM_TSPEC_IE; + + +/* + * BEACON management packets + * + * octet timestamp[8] + * octet beacon interval[2] + * octet capability information[2] + * information element + * octet elemid + * octet length + * octet information[length] + */ + +#define IEEE80211_BEACON_INTERVAL(beacon) \ + ((beacon)[8] | ((beacon)[9] << 8)) +#define IEEE80211_BEACON_CAPABILITY(beacon) \ + ((beacon)[10] | ((beacon)[11] << 8)) + +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +/* bits 8-9 are reserved */ +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +/* bit 12 is reserved */ +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +/* bits 14-15 are reserved */ + +/* + * Authentication Modes + */ + +enum ieee80211_authmode { + IEEE80211_AUTH_NONE = 0, + IEEE80211_AUTH_OPEN = 1, + IEEE80211_AUTH_SHARED = 2, + IEEE80211_AUTH_8021X = 3, + IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */ + /* NB: these are used only for ioctls */ + IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */ + IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */ + IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */ +}; + +#define IEEE80211_PS_MAX_QUEUE 50 /*Maximum no of buffers that can be queues for PS*/ + +#endif /* _NET80211_IEEE80211_H_ */ diff --git a/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h new file mode 100644 index 000000000000..1cb01671c0d3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _IEEE80211_NODE_H_ +#define _IEEE80211_NODE_H_ + +/* + * Node locking definitions. + */ +#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_DESTROY(_nt) if (A_IS_MUTEX_VALID(&(_nt)->nt_nodelock)) { \ + A_MUTEX_DELETE(&(_nt)->nt_nodelock); } + +#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_ASSERT(_nt) + +/* + * Node reference counting definitions. + * + * ieee80211_node_initref initialize the reference count to 1 + * ieee80211_node_incref add a reference + * ieee80211_node_decref remove a reference + * ieee80211_node_dectestref remove a reference and return 1 if this + * is the last reference, otherwise 0 + * ieee80211_node_refcnt reference count for printing (only) + */ +#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1) +#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++) +#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--) +#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 1) +#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt) + +#define IEEE80211_NODE_HASHSIZE 32 +/* simple hash is enough for variation of macaddr */ +#define IEEE80211_NODE_HASH(addr) \ + (((const u8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \ + IEEE80211_NODE_HASHSIZE) + +/* + * Table of ieee80211_node instances. Each ieee80211com + * has at least one for holding the scan candidates. + * When operating as an access point or in ibss mode there + * is a second table for associated stations or neighbors. + */ +struct ieee80211_node_table { + void *nt_wmip; /* back reference */ + A_MUTEX_T nt_nodelock; /* on node table */ + struct bss *nt_node_first; /* information of all nodes */ + struct bss *nt_node_last; /* information of all nodes */ + struct bss *nt_hash[IEEE80211_NODE_HASHSIZE]; + const char *nt_name; /* for debugging */ + u32 nt_scangen; /* gen# for timeout scan */ +#ifdef THREAD_X + A_TIMER nt_inact_timer; + u8 isTimerArmed; /* is the node timer armed */ +#endif + u32 nt_nodeAge; /* node aging time */ +#ifdef OS_ROAM_MANAGEMENT + u32 nt_si_gen; /* gen# for scan indication*/ +#endif +}; + +#ifdef THREAD_X +#define WLAN_NODE_INACT_TIMEOUT_MSEC 20000 +#else +#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000 +#endif + +#define WLAN_NODE_INACT_CNT 4 + +#endif /* _IEEE80211_NODE_H_ */ diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c new file mode 100644 index 000000000000..0fe5f4b1346c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c @@ -0,0 +1,636 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// IEEE 802.11 node handling support. +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include +#define ATH_MODULE_NAME wlan +#include +#include "htc.h" +#include "htc_api.h" +#include +#include +#include +#include +#include + +#define ATH_DEBUG_WLAN ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef ATH_DEBUG_MODULE + +static struct ath_debug_mask_description wlan_debug_desc[] = { + { ATH_DEBUG_WLAN , "General WLAN Node Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(wlan, + "wlan", + "WLAN Node Management", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(wlan_debug_desc), + wlan_debug_desc); + +#endif + +#ifdef THREAD_X +static void wlan_node_timeout(unsigned long arg); +#endif + +static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt, + const u8 *macaddr); + +bss_t * +wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size) +{ + bss_t *ni; + + ni = A_MALLOC_NOWAIT(sizeof(bss_t)); + + if (ni != NULL) { + if (wh_size) + { + ni->ni_buf = A_MALLOC_NOWAIT(wh_size); + if (ni->ni_buf == NULL) { + kfree(ni); + ni = NULL; + return ni; + } + } + } else { + return ni; + } + + /* Make sure our lists are clean */ + ni->ni_list_next = NULL; + ni->ni_list_prev = NULL; + ni->ni_hash_next = NULL; + ni->ni_hash_prev = NULL; + + // + // ni_scangen never initialized before and during suspend/resume of winmobile, + // that some junk has been stored in this, due to this scan list didn't properly updated + // + ni->ni_scangen = 0; + +#ifdef OS_ROAM_MANAGEMENT + ni->ni_si_gen = 0; +#endif + + return ni; +} + +void +wlan_node_free(bss_t *ni) +{ + if (ni->ni_buf != NULL) { + kfree(ni->ni_buf); + } + kfree(ni); +} + +void +wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, + const u8 *macaddr) +{ + int hash; + u32 timeoutValue = 0; + + memcpy(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN); + hash = IEEE80211_NODE_HASH (macaddr); + ieee80211_node_initref (ni); /* mark referenced */ + + timeoutValue = nt->nt_nodeAge; + + ni->ni_tstamp = A_GET_MS (0); + ni->ni_actcnt = WLAN_NODE_INACT_CNT; + + IEEE80211_NODE_LOCK_BH(nt); + + /* Insert at the end of the node list */ + ni->ni_list_next = NULL; + ni->ni_list_prev = nt->nt_node_last; + if(nt->nt_node_last != NULL) + { + nt->nt_node_last->ni_list_next = ni; + } + nt->nt_node_last = ni; + if(nt->nt_node_first == NULL) + { + nt->nt_node_first = ni; + } + + /* Insert into the hash list i.e. the bucket */ + if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL) + { + nt->nt_hash[hash]->ni_hash_prev = ni; + } + ni->ni_hash_prev = NULL; + nt->nt_hash[hash] = ni; + +#ifdef THREAD_X + if (!nt->isTimerArmed) { + A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0); + nt->isTimerArmed = true; + } +#endif + + IEEE80211_NODE_UNLOCK_BH(nt); +} + +static bss_t * +_ieee80211_find_node(struct ieee80211_node_table *nt, + const u8 *macaddr) +{ + bss_t *ni; + int hash; + + IEEE80211_NODE_LOCK_ASSERT(nt); + + hash = IEEE80211_NODE_HASH(macaddr); + for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { + ieee80211_node_incref(ni); /* mark referenced */ + return ni; + } + } + return NULL; +} + +bss_t * +wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr) +{ + bss_t *ni; + + IEEE80211_NODE_LOCK(nt); + ni = _ieee80211_find_node(nt, macaddr); + IEEE80211_NODE_UNLOCK(nt); + return ni; +} + +/* + * Reclaim a node. If this is the last reference count then + * do the normal free work. Otherwise remove it from the node + * table and mark it gone by clearing the back-reference. + */ +void +wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni) +{ + IEEE80211_NODE_LOCK(nt); + + if(ni->ni_list_prev == NULL) + { + /* First in list so fix the list head */ + nt->nt_node_first = ni->ni_list_next; + } + else + { + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + } + + if(ni->ni_list_next == NULL) + { + /* Last in list so fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + } + else + { + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + } + + if(ni->ni_hash_prev == NULL) + { + /* First in list so fix the list head */ + int hash; + hash = IEEE80211_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } + else + { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if(ni->ni_hash_next != NULL) + { + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + } + wlan_node_free(ni); + + IEEE80211_NODE_UNLOCK(nt); +} + +static void +wlan_node_dec_free(bss_t *ni) +{ + if (ieee80211_node_dectestref(ni)) { + wlan_node_free(ni); + } +} + +void +wlan_free_allnodes(struct ieee80211_node_table *nt) +{ + bss_t *ni; + + while ((ni = nt->nt_node_first) != NULL) { + wlan_node_reclaim(nt, ni); + } +} + +void +wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, + void *arg) +{ + bss_t *ni; + u32 gen; + + gen = ++nt->nt_scangen; + + IEEE80211_NODE_LOCK(nt); + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + if (ni->ni_scangen != gen) { + ni->ni_scangen = gen; + (void) ieee80211_node_incref(ni); + (*f)(arg, ni); + wlan_node_dec_free(ni); + } + } + IEEE80211_NODE_UNLOCK(nt); +} + +/* + * Node table support. + */ +void +wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt) +{ + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%lx\n", (unsigned long)nt)); + IEEE80211_NODE_LOCK_INIT(nt); + + A_REGISTER_MODULE_DEBUG_INFO(wlan); + + nt->nt_node_first = nt->nt_node_last = NULL; + for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++) + { + nt->nt_hash[i] = NULL; + } + +#ifdef THREAD_X + A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt); + nt->isTimerArmed = false; +#endif + nt->nt_wmip = wmip; + nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC; + + // + // nt_scangen never initialized before and during suspend/resume of winmobile, + // that some junk has been stored in this, due to this scan list didn't properly updated + // + nt->nt_scangen = 0; + +#ifdef OS_ROAM_MANAGEMENT + nt->nt_si_gen = 0; +#endif +} + +void +wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge) +{ + nt->nt_nodeAge = nodeAge; + return; +} +void +wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt) +{ +#ifdef THREAD_X + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + + } + bss = nextBss; + } +#else + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN]; + u32 timeoutValue = 0; + u32 now = A_GET_MS(0); + timeoutValue = nt->nt_nodeAge; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + + if (((now - bss->ni_tstamp) > timeoutValue) || --bss->ni_actcnt == 0) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + } + } + bss = nextBss; + } +#endif +} + +#ifdef THREAD_X +static void +wlan_node_timeout (unsigned long arg) +{ + struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg; + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false; + u32 timeoutValue = 0; + u32 now = A_GET_MS(0); + + timeoutValue = nt->nt_nodeAge; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + + if ((now - bss->ni_tstamp) > timeoutValue) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + } + else + { + /* + * Re-arm timer, only when we have a bss other than + * current bss AND it is not aged-out. + */ + reArmTimer = true; + } + } + bss = nextBss; + } + + if (reArmTimer) + A_TIMEOUT_MS (&nt->nt_inact_timer, timeoutValue, 0); + + nt->isTimerArmed = reArmTimer; +} +#endif + +void +wlan_node_table_cleanup(struct ieee80211_node_table *nt) +{ +#ifdef THREAD_X + A_UNTIMEOUT(&nt->nt_inact_timer); + A_DELETE_TIMER(&nt->nt_inact_timer); +#endif + wlan_free_allnodes(nt); + IEEE80211_NODE_LOCK_DESTROY(nt); +} + +bss_t * +wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID) +{ + bss_t *ni = NULL; + u8 *pIESsid = NULL; + + IEEE80211_NODE_LOCK (nt); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + pIESsid = ni->ni_cie.ie_ssid; + if (pIESsid[1] <= 32) { + + // Step 1 : Check SSID + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { + + // + // Step 2.1 : Check MatchSSID is true, if so, return Matched SSID + // Profile, otherwise check whether WPA2 or WPA + // + if (true == bMatchSSID) { + ieee80211_node_incref (ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + + // Step 2 : if SSID matches, check WPA or WPA2 + if (true == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) { + ieee80211_node_incref (ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + if (false == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) { + ieee80211_node_incref(ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + } + } + } + + IEEE80211_NODE_UNLOCK (nt); + + return NULL; +} + +void +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni) +{ + IEEE80211_NODE_LOCK (nt); + wlan_node_dec_free (ni); + IEEE80211_NODE_UNLOCK (nt); +} + +void +wlan_node_remove_core (struct ieee80211_node_table *nt, bss_t *ni) +{ + if(ni->ni_list_prev == NULL) + { + /* First in list so fix the list head */ + nt->nt_node_first = ni->ni_list_next; + } + else + { + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + } + + if(ni->ni_list_next == NULL) + { + /* Last in list so fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + } + else + { + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + } + + if(ni->ni_hash_prev == NULL) + { + /* First in list so fix the list head */ + int hash; + hash = IEEE80211_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } + else + { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if(ni->ni_hash_next != NULL) + { + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + } +} + +bss_t * +wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid) +{ + bss_t *bss, *nextBss; + + IEEE80211_NODE_LOCK(nt); + + bss = nt->nt_node_first; + + while (bss != NULL) + { + nextBss = bss->ni_list_next; + + if (memcmp(bssid, bss->ni_macaddr, 6) == 0) + { + wlan_node_remove_core (nt, bss); + IEEE80211_NODE_UNLOCK(nt); + return bss; + } + + bss = nextBss; + } + + IEEE80211_NODE_UNLOCK(nt); + return NULL; +} + +bss_t * +wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp) +{ + bss_t *ni = NULL; + bss_t *best_ni = NULL; + u8 *pIESsid = NULL; + + IEEE80211_NODE_LOCK (nt); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + pIESsid = ni->ni_cie.ie_ssid; + if (pIESsid[1] <= 32) { + + // Step 1 : Check SSID + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { + + if (ni->ni_cie.ie_capInfo & 0x10) + { + + if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode)) + { + /* WPA2 */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode)) + { + /* WPA */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + else if (WEP_CRYPT == pairwiseCryptoType) + { + /* WEP */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + } + else + { + /* open AP */ + if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType)) + { + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + } + } + } + } + + IEEE80211_NODE_UNLOCK (nt); + + return best_ni; +} + diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c new file mode 100644 index 000000000000..07b8313b16e8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c @@ -0,0 +1,199 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// IEEE 802.11 input handling. +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include +#include +#include + +#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ + if ((_len) < (_minlen)) { \ + return A_EINVAL; \ + } \ +} while (0) + +#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ + if ((__elem) == NULL) { \ + return A_EINVAL; \ + } \ + if ((__elem)[1] > (__maxlen)) { \ + return A_EINVAL; \ + } \ +} while (0) + + +/* unaligned little endian access */ +#define LE_READ_2(p) \ + ((u16) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8))) + +#define LE_READ_4(p) \ + ((u32) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \ + (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24))) + + +static int __inline +iswpaoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); +} + +static int __inline +iswmmoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); +} + +/* unused functions for now */ +#if 0 +static int __inline +iswmmparam(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; +} + +static int __inline +iswmminfo(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE; +} +#endif + +static int __inline +isatherosoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); +} + +static int __inline +iswscoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI); +} + +int +wlan_parse_beacon(u8 *buf, int framelen, struct ieee80211_common_ie *cie) +{ + u8 *frm, *efrm; + u8 elemid_ssid = false; + + frm = buf; + efrm = (u8 *) (frm + framelen); + + /* + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + * [tlv] supported rates + * [tlv] country information + * [tlv] parameter set (FH/DS) + * [tlv] erp information + * [tlv] extended supported rates + * [tlv] WMM + * [tlv] WPA or RSN + * [tlv] Atheros Advanced Capabilities + */ + IEEE80211_VERIFY_LENGTH(efrm - frm, 12); + A_MEMZERO(cie, sizeof(*cie)); + + cie->ie_tstamp = frm; frm += 8; + cie->ie_beaconInt = A_LE2CPU16(*(u16 *)frm); frm += 2; + cie->ie_capInfo = A_LE2CPU16(*(u16 *)frm); frm += 2; + cie->ie_chan = 0; + + while (frm < efrm) { + switch (*frm) { + case IEEE80211_ELEMID_SSID: + if (!elemid_ssid) { + cie->ie_ssid = frm; + elemid_ssid = true; + } + break; + case IEEE80211_ELEMID_RATES: + cie->ie_rates = frm; + break; + case IEEE80211_ELEMID_COUNTRY: + cie->ie_country = frm; + break; + case IEEE80211_ELEMID_FHPARMS: + break; + case IEEE80211_ELEMID_DSPARMS: + cie->ie_chan = frm[2]; + break; + case IEEE80211_ELEMID_TIM: + cie->ie_tim = frm; + break; + case IEEE80211_ELEMID_IBSSPARMS: + break; + case IEEE80211_ELEMID_XRATES: + cie->ie_xrates = frm; + break; + case IEEE80211_ELEMID_ERP: + if (frm[1] != 1) { + //A_PRINTF("Discarding ERP Element - Bad Len\n"); + return A_EINVAL; + } + cie->ie_erp = frm[2]; + break; + case IEEE80211_ELEMID_RSN: + cie->ie_rsn = frm; + break; + case IEEE80211_ELEMID_HTCAP_ANA: + cie->ie_htcap = frm; + break; + case IEEE80211_ELEMID_HTINFO_ANA: + cie->ie_htop = frm; + break; +#ifdef WAPI_ENABLE + case IEEE80211_ELEMID_WAPI: + cie->ie_wapi = frm; + break; +#endif + case IEEE80211_ELEMID_VENDOR: + if (iswpaoui(frm)) { + cie->ie_wpa = frm; + } else if (iswmmoui(frm)) { + cie->ie_wmm = frm; + } else if (isatherosoui(frm)) { + cie->ie_ath = frm; + } else if(iswscoui(frm)) { + cie->ie_wsc = frm; + } + break; + default: + break; + } + frm += frm[1] + 2; + } + IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE); + IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN); + + return 0; +} diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c new file mode 100644 index 000000000000..bc91599d9bf6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This module implements frequently used wlan utilies +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include + +/* + * converts ieee channel number to frequency + */ +u16 wlan_ieee2freq(int chan) +{ + if (chan == 14) { + return 2484; + } + if (chan < 14) { /* 0-13 */ + return (2407 + (chan*5)); + } + if (chan < 27) { /* 15-26 */ + return (2512 + ((chan-15)*20)); + } + return (5000 + (chan*5)); +} + +/* + * Converts MHz frequency to IEEE channel number. + */ +u32 wlan_freq2ieee(u16 freq) +{ + if (freq == 2484) + return 14; + if (freq < 2484) + return (freq - 2407) / 5; + if (freq < 5000) + return 15 + ((freq - 2512) / 20); + return (freq - 5000) / 5; +} diff --git a/trunk/drivers/staging/ath6kl/wmi/wmi.c b/trunk/drivers/staging/ath6kl/wmi/wmi.c new file mode 100644 index 000000000000..c7b5e5cf9df7 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wmi/wmi.c @@ -0,0 +1,6444 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This module implements the hardware independent layer of the +// Wireless Module Interface (WMI) protocol. +// +// Author(s): ="Atheros" +//============================================================================== + +#include +#include +#include +#include "htc.h" +#include "htc_api.h" +#include "wmi.h" +#include +#include +#include +#include +#include "dset_api.h" +#include "wmi_host.h" +#include "a_drv.h" +#include "a_drv_api.h" +#define ATH_MODULE_NAME wmi +#include "a_debug.h" +#include "dbglog_api.h" +#include "roaming.h" +#include "cfg80211.h" + +#define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef ATH_DEBUG_MODULE + +static struct ath_debug_mask_description wmi_debug_desc[] = { + { ATH_DEBUG_WMI , "General WMI Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi, + "wmi", + "Wireless Module Interface", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc), + wmi_debug_desc); + +#endif + +#ifndef REXOS +#define DBGARG _A_FUNCNAME_ +#define DBGFMT "%s() : " +#define DBG_WMI ATH_DEBUG_WMI +#define DBG_ERROR ATH_DEBUG_ERR +#define DBG_WMI2 ATH_DEBUG_WMI +#define A_DPRINTF AR_DEBUG_PRINTF +#endif + +static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_sync_point(struct wmi_t *wmip); + +static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, + int len); +#ifdef CONFIG_HOST_DSET_SUPPORT +static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, + int len); +#endif /* CONFIG_HOST_DSET_SUPPORT */ + + +static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); + +static int +wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); + + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static int +wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len); +#endif + +static int +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static bool +wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex); + +static int +wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len); + +int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag); + +u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); +u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); + +void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +static int wmi_send_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +static int wmi_send_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +static int +wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len); +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int); +static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int); +static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int); +static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_hci_event_rx(struct wmi_t *, u8 *, int); + +#ifdef WAPI_ENABLE +static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +#endif + +#if defined(UNDER_CE) +#if defined(NDIS51_MINIPORT) +unsigned int processDot11Hdr = 0; +#else +unsigned int processDot11Hdr = 1; +#endif +#else +extern unsigned int processDot11Hdr; +#endif + +int wps_enable; +static const s32 wmi_rateTable[][2] = { + //{W/O SGI, with SGI} + {1000, 1000}, + {2000, 2000}, + {5500, 5500}, + {11000, 11000}, + {6000, 6000}, + {9000, 9000}, + {12000, 12000}, + {18000, 18000}, + {24000, 24000}, + {36000, 36000}, + {48000, 48000}, + {54000, 54000}, + {6500, 7200}, + {13000, 14400}, + {19500, 21700}, + {26000, 28900}, + {39000, 43300}, + {52000, 57800}, + {58500, 65000}, + {65000, 72200}, + {13500, 15000}, + {27000, 30000}, + {40500, 45000}, + {54000, 60000}, + {81000, 90000}, + {108000, 120000}, + {121500, 135000}, + {135000, 150000}, + {0, 0}}; + +#define MODE_A_SUPPORT_RATE_START ((s32) 4) +#define MODE_A_SUPPORT_RATE_STOP ((s32) 11) + +#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START +#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP + +#define MODE_B_SUPPORT_RATE_START ((s32) 0) +#define MODE_B_SUPPORT_RATE_STOP ((s32) 3) + +#define MODE_G_SUPPORT_RATE_START ((s32) 0) +#define MODE_G_SUPPORT_RATE_STOP ((s32) 11) + +#define MODE_GHT20_SUPPORT_RATE_START ((s32) 0) +#define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19) + +#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1) + +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ +const u8 up_to_ac[]= { + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO, + }; + +/* This stuff is used when we want a simple layer-3 visibility */ +typedef PREPACK struct _iphdr { + u8 ip_ver_hdrlen; /* version and hdr length */ + u8 ip_tos; /* type of service */ + u16 ip_len; /* total length */ + u16 ip_id; /* identification */ + s16 ip_off; /* fragment offset field */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u8 ip_ttl; /* time to live */ + u8 ip_p; /* protocol */ + u16 ip_sum; /* checksum */ + u8 ip_src[4]; /* source and dest address */ + u8 ip_dst[4]; +} POSTPACK iphdr; + +static s16 rssi_event_value = 0; +static s16 snr_event_value = 0; + +bool is_probe_ssid = false; + +void * +wmi_init(void *devt) +{ + struct wmi_t *wmip; + + A_REGISTER_MODULE_DEBUG_INFO(wmi); + + wmip = A_MALLOC (sizeof(struct wmi_t)); + if (wmip == NULL) { + return (NULL); + } + A_MEMZERO(wmip, sizeof(struct wmi_t )); +#ifdef THREAD_X + INIT_WMI_LOCK(wmip); +#else + A_MUTEX_INIT(&wmip->wmi_lock); +#endif + wmip->wmi_devt = devt; + wlan_node_table_init(wmip, &wmip->wmi_scan_table); + wmi_qos_state_init(wmip); + + wmip->wmi_powerMode = REC_POWER; + wmip->wmi_phyMode = WMI_11G_MODE; + + wmip->wmi_pair_crypto_type = NONE_CRYPT; + wmip->wmi_grp_crypto_type = NONE_CRYPT; + + wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1; + wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1; + + return (wmip); +} + +void +wmi_qos_state_init(struct wmi_t *wmip) +{ + u8 i; + + if (wmip == NULL) { + return; + } + LOCK_WMI(wmip); + + /* Initialize QoS States */ + wmip->wmi_numQoSStream = 0; + + wmip->wmi_fatPipeExists = 0; + + for (i=0; i < WMM_NUM_AC; i++) { + wmip->wmi_streamExistsForAC[i]=0; + } + + UNLOCK_WMI(wmip); + + A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); +} + +void +wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid) +{ + A_ASSERT( eid != ENDPOINT_UNUSED); + wmip->wmi_endpoint_id = eid; +} + +HTC_ENDPOINT_ID +wmi_get_control_ep(struct wmi_t * wmip) +{ + return(wmip->wmi_endpoint_id); +} + +void +wmi_shutdown(struct wmi_t *wmip) +{ + if (wmip != NULL) { + wlan_node_table_cleanup(&wmip->wmi_scan_table); + if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) { +#ifdef THREAD_X + DELETE_WMI_LOCK(&wmip); +#else + A_MUTEX_DELETE(&wmip->wmi_lock); +#endif + } + kfree(wmip); + } +} + +/* + * performs DIX to 802.3 encapsulation for transmit packets. + * uses passed in buffer. Returns buffer or NULL if failed. + * Assumes the entire DIX header is contigous and that there is + * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. + */ +int +wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf) +{ + u8 *datap; + u16 typeorlen; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_HEADROOM(osbuf) < + (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) + { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); + + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { + /* + * packet is already in 802.3 format - return success + */ + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); + return (0); + } + + /* + * Save mac fields and length to be inserted later + */ + memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); + memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR)); + + /* + * Make room for LLC+SNAP headers + */ + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + datap = A_NETBUF_DATA(osbuf); + + memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + llcHdr->dsap = 0xAA; + llcHdr->ssap = 0xAA; + llcHdr->cntl = 0x03; + llcHdr->orgCode[0] = 0x0; + llcHdr->orgCode[1] = 0x0; + llcHdr->orgCode[2] = 0x0; + llcHdr->etherType = typeorlen; + + return (0); +} + +int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS) +{ + switch(*pVersion){ + case 0: + return (0); + case WMI_META_VERSION_1: + { + WMI_TX_META_V1 *pV1= NULL; + A_ASSERT(osbuf != NULL); + if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { + return A_NO_MEMORY; + } + + pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf); + /* the pktID is used in conjunction with txComplete messages + * allowing the target to notify which tx requests have been + * completed and how. */ + pV1->pktID = 0; + /* the ratePolicyID allows the host to specify which rate policy + * to use for transmitting this packet. 0 means use default behavior. */ + pV1->ratePolicyID = 0; + A_ASSERT(pVersion != NULL); + /* the version must be used to populate the meta field of the WMI_DATA_HDR */ + *pVersion = WMI_META_VERSION_1; + return (0); + } + case WMI_META_VERSION_2: + { + WMI_TX_META_V2 *pV2 ; + A_ASSERT(osbuf != NULL); + if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { + return A_NO_MEMORY; + } + pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf); + memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2)); + return (0); + } + default: + return (0); + } +} + +/* Adds a WMI data header */ +int +wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, + WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS) +{ + WMI_DATA_HDR *dtHdr; +// u8 metaVersion = 0; + int status; + + A_ASSERT(osbuf != NULL); + + /* adds the meta data field after the wmi data hdr. If metaVersion + * is returns 0 then no meta field was added. */ + if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) { + return status; + } + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR)); + + WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType); + WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type); + + if (bMoreData) { + WMI_DATA_HDR_SET_MORE_BIT(dtHdr); + } + + WMI_DATA_HDR_SET_META(dtHdr, metaVersion); + + dtHdr->info3 = 0; + + return (0); +} + + +u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled) +{ + u8 *datap; + u8 trafficClass = WMM_AC_BE; + u16 ipType = IP_ETHERTYPE; + WMI_DATA_HDR *dtHdr; + u8 streamExists = 0; + u8 userPriority; + u32 hdrsize, metasize; + ATH_LLC_SNAP_HDR *llcHdr; + + WMI_CREATE_PSTREAM_CMD cmd; + + A_ASSERT(osbuf != NULL); + + // + // Initialize header size + // + hdrsize = 0; + + datap = A_NETBUF_DATA(osbuf); + dtHdr = (WMI_DATA_HDR *)datap; + metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0; + + if (!wmmEnabled) + { + /* If WMM is disabled all traffic goes as BE traffic */ + userPriority = 0; + } + else + { + if (processDot11Hdr) + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + + hdrsize); + + + } + else + { + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + + sizeof(ATH_MAC_HDR)); + } + + if (llcHdr->etherType == A_CPU2BE16(ipType)) + { + /* Extract the endpoint info from the TOS field in the IP header */ + + userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority); + } + else + { + userPriority = layer2Priority & 0x7; + } + } + + + /* workaround for WMM S5 */ + if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority))) + { + userPriority = 1; + } + + trafficClass = convert_userPriority_to_trafficClass(userPriority); + + WMI_DATA_HDR_SET_UP(dtHdr, userPriority); + /* lower 3-bits are 802.1d priority */ + //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; + + LOCK_WMI(wmip); + streamExists = wmip->wmi_fatPipeExists; + UNLOCK_WMI(wmip); + + if (!(streamExists & (1 << trafficClass))) + { + + A_MEMZERO(&cmd, sizeof(cmd)); + cmd.trafficClass = trafficClass; + cmd.userPriority = userPriority; + cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT; + /* Implicit streams are created with TSID 0xFF */ + + cmd.tsid = WMI_IMPLICIT_PSTREAM; + wmi_create_pstream_cmd(wmip, &cmd); + } + + return trafficClass; +} + +int +wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode) +{ + u8 *datap; + u16 typeorlen; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + struct ieee80211_frame *wh; + u32 hdrsize; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_HEADROOM(osbuf) < + (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) + { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); + + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { +/* + * packet is already in 802.3 format - return success + */ + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); + goto AddDot11Hdr; + } + + /* + * Save mac fields and length to be inserted later + */ + memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); + memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR)); + + // Remove the Ethernet hdr + A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR)); + /* + * Make room for LLC+SNAP headers + */ + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + datap = A_NETBUF_DATA(osbuf); + + llcHdr = (ATH_LLC_SNAP_HDR *)(datap); + llcHdr->dsap = 0xAA; + llcHdr->ssap = 0xAA; + llcHdr->cntl = 0x03; + llcHdr->orgCode[0] = 0x0; + llcHdr->orgCode[1] = 0x0; + llcHdr->orgCode[2] = 0x0; + llcHdr->etherType = typeorlen; + +AddDot11Hdr: + /* Make room for 802.11 hdr */ + if (wmip->wmi_is_wmm_enabled) + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) + { + return A_NO_MEMORY; + } + wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); + wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS; + } + else + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32)); + if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) + { + return A_NO_MEMORY; + } + wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); + wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA; + } + /* Setup the SA & DA */ + IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac); + + if (mode == INFRA_NETWORK) { + IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac); + } + else if (mode == ADHOC_NETWORK) { + IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac); + } + + return (0); +} + +int +wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf) +{ + u8 *datap; + struct ieee80211_frame *pwh,wh; + u8 type,subtype; + ATH_LLC_SNAP_HDR *llcHdr; + ATH_MAC_HDR macHdr; + u32 hdrsize; + + A_ASSERT(osbuf != NULL); + datap = A_NETBUF_DATA(osbuf); + + pwh = (struct ieee80211_frame *)datap; + type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame)); + + /* strip off the 802.11 hdr*/ + if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + A_NETBUF_PULL(osbuf, hdrsize); + } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) { + A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame)); + } + + datap = A_NETBUF_DATA(osbuf); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap); + + macHdr.typeOrLen = llcHdr->etherType; + A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac)); + A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac)); + + switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); + break; + case IEEE80211_FC1_DIR_TODS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); + break; + case IEEE80211_FC1_DIR_FROMDS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3); + break; + case IEEE80211_FC1_DIR_DSTODS: + break; + } + + // Remove the LLC Hdr. + A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)); + + // Insert the ATH MAC hdr. + + A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR)); + datap = A_NETBUF_DATA(osbuf); + + memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR)); + + return 0; +} + +/* + * performs 802.3 to DIX encapsulation for received packets. + * Assumes the entire 802.3 header is contigous. + */ +int +wmi_dot3_2_dix(void *osbuf) +{ + u8 *datap; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + datap = A_NETBUF_DATA(osbuf); + + memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR)); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + macHdr.typeOrLen = llcHdr->etherType; + + if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + return (0); +} + +/* + * Removes a WMI data header + */ +int +wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf) +{ + A_ASSERT(osbuf != NULL); + + return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR))); +} + +void +wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg) +{ + wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg); +} + +/* + * WMI Extended Event received from Target. + */ +int +wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf) +{ + WMIX_CMD_HDR *cmd; + u16 id; + u8 *datap; + u32 len; + int status = 0; + + if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + switch (id) { + case (WMIX_DSETOPENREQ_EVENTID): + status = wmi_dset_open_req_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_DSET_SUPPORT + case (WMIX_DSETCLOSE_EVENTID): + status = wmi_dset_close_rx(wmip, datap, len); + break; + case (WMIX_DSETDATAREQ_EVENTID): + status = wmi_dset_data_req_rx(wmip, datap, len); + break; +#endif /* CONFIG_HOST_DSET_SUPPORT */ + case (WMIX_HB_CHALLENGE_RESP_EVENTID): + wmi_hbChallengeResp_rx(wmip, datap, len); + break; + case (WMIX_DBGLOG_EVENTID): + wmi_dbglog_event_rx(wmip, datap, len); + break; +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) + case (WMIX_PROF_COUNT_EVENTID): + wmi_prof_count_rx(wmip, datap, len); + break; +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + return status; +} + +/* + * Control Path + */ +u32 cmdRecvNum; + +int +wmi_control_rx(struct wmi_t *wmip, void *osbuf) +{ + WMI_CMD_HDR *cmd; + u16 id; + u8 *datap; + u32 len, i, loggingReq; + int status = 0; + + A_ASSERT(osbuf != NULL); + if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) { + A_NETBUF_FREE(osbuf); + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + loggingReq = 0; + + ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS, + &loggingReq); + + if(loggingReq) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id)); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum)); + for(i = 0; i < len; i++) + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i])); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n")); + } + + LOCK_WMI(wmip); + cmdRecvNum++; + UNLOCK_WMI(wmip); + + switch (id) { + case (WMI_GET_BITRATE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG)); + status = wmi_bitrate_reply_rx(wmip, datap, len); + break; + case (WMI_GET_CHANNEL_LIST_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG)); + status = wmi_channelList_reply_rx(wmip, datap, len); + break; + case (WMI_GET_TX_PWR_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG)); + status = wmi_txPwr_reply_rx(wmip, datap, len); + break; + case (WMI_READY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG)); + status = wmi_ready_event_rx(wmip, datap, len); + A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt); + break; + case (WMI_CONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG)); + status = wmi_connect_event_rx(wmip, datap, len); + break; + case (WMI_DISCONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG)); + status = wmi_disconnect_event_rx(wmip, datap, len); + break; + case (WMI_PEER_NODE_EVENTID): + A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG)); + status = wmi_peer_node_event_rx(wmip, datap, len); + break; + case (WMI_TKIP_MICERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG)); + status = wmi_tkip_micerr_event_rx(wmip, datap, len); + break; + case (WMI_BSSINFO_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG)); + { + /* + * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR + * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer + * and reconstruct the WMI_BSS_INFO_HDR in its place + */ + WMI_BSS_INFO_HDR2 bih2; + WMI_BSS_INFO_HDR *bih; + memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2)); + + A_NETBUF_PUSH(osbuf, 4); + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + bih = (WMI_BSS_INFO_HDR *)datap; + + bih->channel = bih2.channel; + bih->frameType = bih2.frameType; + bih->snr = bih2.snr; + bih->rssi = bih2.snr - 95; + bih->ieMask = bih2.ieMask; + memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN); + + status = wmi_bssInfo_event_rx(wmip, datap, len); + } + break; + case (WMI_REGDOMAIN_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG)); + status = wmi_regDomain_event_rx(wmip, datap, len); + break; + case (WMI_PSTREAM_TIMEOUT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG)); + status = wmi_pstream_timeout_event_rx(wmip, datap, len); + break; + case (WMI_NEIGHBOR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG)); + status = wmi_neighborReport_event_rx(wmip, datap, len); + break; + case (WMI_SCAN_COMPLETE_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG)); + status = wmi_scanComplete_rx(wmip, datap, len); + break; + case (WMI_CMDERROR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG)); + status = wmi_errorEvent_rx(wmip, datap, len); + break; + case (WMI_REPORT_STATISTICS_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG)); + status = wmi_statsEvent_rx(wmip, datap, len); + break; + case (WMI_RSSI_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_rssiThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_ERROR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG)); + status = wmi_reportErrorEvent_rx(wmip, datap, len); + break; + case (WMI_OPT_RX_FRAME_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG)); + status = wmi_opt_frame_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_TBL_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG)); + status = wmi_roam_tbl_event_rx(wmip, datap, len); + break; + case (WMI_EXTENSION_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG)); + status = wmi_control_rx_xtnd(wmip, osbuf); + break; + case (WMI_CAC_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG)); + status = wmi_cac_event_rx(wmip, datap, len); + break; + case (WMI_CHANNEL_CHANGE_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG)); + status = wmi_channel_change_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_DATA_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG)); + status = wmi_roam_data_event_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_TCMD_SUPPORT + case (WMI_TEST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG)); + status = wmi_tcmd_test_report_rx(wmip, datap, len); + break; +#endif + case (WMI_GET_FIXRATES_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG)); + status = wmi_ratemask_reply_rx(wmip, datap, len); + break; + case (WMI_TX_RETRY_ERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG)); + status = wmi_txRetryErrEvent_rx(wmip, datap, len); + break; + case (WMI_SNR_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_snrThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_LQ_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_lqThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_APLIST_EVENTID): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n")); + status = wmi_aplistEvent_rx(wmip, datap, len); + break; + case (WMI_GET_KEEPALIVE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG)); + status = wmi_keepalive_reply_rx(wmip, datap, len); + break; + case (WMI_GET_WOW_LIST_EVENTID): + status = wmi_get_wow_list_event_rx(wmip, datap, len); + break; + case (WMI_GET_PMKID_LIST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG)); + status = wmi_get_pmkid_list_event_rx(wmip, datap, len); + break; + case (WMI_PSPOLL_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG)); + status = wmi_pspoll_event_rx(wmip, datap, len); + break; + case (WMI_DTIMEXPIRY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG)); + status = wmi_dtimexpiry_event_rx(wmip, datap, len); + break; + case (WMI_SET_PARAMS_REPLY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); + status = wmi_set_params_event_rx(wmip, datap, len); + break; + case (WMI_ADDBA_REQ_EVENTID): + status = wmi_addba_req_event_rx(wmip, datap, len); + break; + case (WMI_ADDBA_RESP_EVENTID): + status = wmi_addba_resp_event_rx(wmip, datap, len); + break; + case (WMI_DELBA_REQ_EVENTID): + status = wmi_delba_req_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_BTCOEX_CONFIG_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG)); + status = wmi_btcoex_config_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_BTCOEX_STATS_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG)); + status = wmi_btcoex_stats_event_rx(wmip, datap, len); + break; + case (WMI_TX_COMPLETE_EVENTID): + { + int index; + TX_COMPLETE_MSG_V1 *pV1; + WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap; + A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType); + + for(index = 0 ; index < pEv->numMessages ; index++) { + pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1)); + A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures); + } + } + break; + case (WMI_HCI_EVENT_EVENTID): + status = wmi_hci_event_rx(wmip, datap, len); + break; +#ifdef WAPI_ENABLE + case (WMI_WAPI_REKEY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG)); + status = wmi_wapi_rekey_event_rx(wmip, datap, len); + break; +#endif + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + A_NETBUF_FREE(osbuf); + + return status; +} + +/* Send a "simple" wmi command -- one with no arguments */ +static int +wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); +} + +/* Send a "simple" extended wmi command -- one with no arguments. + Enabling this command only if GPIO or profiling support is enabled. + This is to suppress warnings on some platforms */ +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +static int +wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); +} +#endif + +static int +wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap; + + if (len < sizeof(WMI_READY_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + wmip->wmi_ready = true; + A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability, + ev->sw_version, ev->abi_version); + + return 0; +} + +#define LE_READ_4(p) \ + ((u32) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \ + (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24))) + +static int __inline +iswmmoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); +} + +static int __inline +iswmmparam(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; +} + + +static int +wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CONNECT_EVENT *ev; + u8 *pie,*peie; + + if (len < sizeof(WMI_CONNECT_EVENT)) + { + return A_EINVAL; + } + ev = (WMI_CONNECT_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + DBGARG, ev->channel, + ev->bssid[0], ev->bssid[1], ev->bssid[2], + ev->bssid[3], ev->bssid[4], ev->bssid[5])); + + memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); + + /* initialize pointer to start of assoc rsp IEs */ + pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16) ; /* associd */ + + /* initialize pointer to end of assoc rsp IEs */ + peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen; + + while (pie < peie) + { + switch (*pie) + { + case IEEE80211_ELEMID_VENDOR: + if (iswmmoui(pie)) + { + if(iswmmparam (pie)) + { + wmip->wmi_is_wmm_enabled = true; + } + } + break; + } + + if (wmip->wmi_is_wmm_enabled) + { + break; + } + pie += pie[1] + 2; + } + + A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, + ev->listenInterval, ev->beaconInterval, + (NETWORK_TYPE) ev->networkType, ev->beaconIeLen, + ev->assocReqLen, ev->assocRespLen, + ev->assocInfo); + + return 0; +} + +static int +wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_REG_DOMAIN_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_REG_DOMAIN_EVENT *)datap; + + A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain); + + return 0; +} + +static int +wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_NEIGHBOR_REPORT_EVENT *ev; + int numAps; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap; + numAps = ev->numberOfAps; + + if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) { + return A_EINVAL; + } + + A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor); + + return 0; +} + +static int +wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_DISCONNECT_EVENT *ev; + wmip->wmi_traffic_class = 100; + + if (len < sizeof(WMI_DISCONNECT_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_DISCONNECT_EVENT *)datap; + + A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid)); + + wmip->wmi_is_wmm_enabled = false; + wmip->wmi_pair_crypto_type = NONE_CRYPT; + wmip->wmi_grp_crypto_type = NONE_CRYPT; + + A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, + ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); + + return 0; +} + +static int +wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PEER_NODE_EVENT *ev; + + if (len < sizeof(WMI_PEER_NODE_EVENT)) { + return A_EINVAL; + } + ev = (WMI_PEER_NODE_EVENT *)datap; + if (ev->eventCode == PEER_NODE_JOIN_EVENT) { + A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG)); + } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) { + A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG)); + } + + A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr); + + return 0; +} + +static int +wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TKIP_MICERR_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_TKIP_MICERR_EVENT *)datap; + A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast); + + return 0; +} + +static int +wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + bss_t *bss = NULL; + WMI_BSS_INFO_HDR *bih; + u8 *buf; + u32 nodeCachingAllowed = 1; + u8 cached_ssid_len = 0; + u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0}; + u8 beacon_ssid_len = 0; + + if (len <= sizeof(WMI_BSS_INFO_HDR)) { + return A_EINVAL; + } + + bih = (WMI_BSS_INFO_HDR *)datap; + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + + if (bih->rssi > 0) { + if (NULL == bss) + return 0; //no node found in the table, just drop the node with incorrect RSSI + else + bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX + } + + A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len); + /* What is driver config for wlan node caching? */ + if(ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_GET_WLANNODECACHING, + &nodeCachingAllowed) != 0) { + wmi_node_return(wmip, bss); + return A_EINVAL; + } + + if(!nodeCachingAllowed) { + wmi_node_return(wmip, bss); + return 0; + } + + buf = datap + sizeof(WMI_BSS_INFO_HDR); + len -= sizeof(WMI_BSS_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, " + "bssid \"%pM\"\n", DBGARG, bih->channel, + (unsigned char) bih->rssi, bih->bssid)); + + if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) { + wmi_node_return(wmip, bss); + return 0; + } + + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + + /* In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so cache the probe-resp-ssid if already present. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType)) + { + u8 *ie_ssid; + + ie_ssid = bss->ni_cie.ie_ssid; + if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0)) + { + cached_ssid_len = ie_ssid[1]; + memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len); + } + } + + /* + * Use the current average rssi of associated AP base on assumpiton + * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically + * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...) + * The average value of RSSI give end-user better feeling for instance value of scan result + * It also sync up RSSI info in GUI between scan result and RSSI signal icon + */ + if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) { + bih->rssi = bss->ni_rssi; + bih->snr = bss->ni_snr; + } + + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + /* beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid */ + beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; + + /* If ssid is cached for this hidden AP, then change buffer len accordingly. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && + (0 != cached_ssid_len) && + (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) + { + len += (cached_ssid_len - beacon_ssid_len); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_rssi = bih->rssi; + A_ASSERT(bss->ni_buf != NULL); + + /* In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so place the cached-ssid(probe-resp) in the bssinfo. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && + (0 != cached_ssid_len) && + (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) + { + u8 *ni_buf = bss->ni_buf; + int buf_len = len; + + /* copy the first 14 bytes such as + * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */ + memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); + + ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; + ni_buf += (SSID_IE_LEN_INDEX + 1); + + buf += (SSID_IE_LEN_INDEX + 1); + buf_len -= (SSID_IE_LEN_INDEX + 1); + + /* copy the cached ssid */ + memcpy(ni_buf, cached_ssid_buf, cached_ssid_len); + ni_buf += cached_ssid_len; + + buf += beacon_ssid_len; + buf_len -= beacon_ssid_len; + + if (cached_ssid_len > beacon_ssid_len) + buf_len -= (cached_ssid_len - beacon_ssid_len); + + /* now copy the rest of bytes */ + memcpy(ni_buf, buf, buf_len); + } + else + memcpy(bss->ni_buf, buf, len); + + bss->ni_framelen = len; + if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) { + wlan_node_free(bss); + return A_EINVAL; + } + + /* + * Update the frequency in ie_chan, overwriting of channel number + * which is done in wlan_parse_beacon + */ + bss->ni_cie.ie_chan = bih->channel; + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return 0; +} + +static int +wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + bss_t *bss; + WMI_OPT_RX_INFO_HDR *bih; + u8 *buf; + + if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) { + return A_EINVAL; + } + + bih = (WMI_OPT_RX_INFO_HDR *)datap; + buf = datap + sizeof(WMI_OPT_RX_INFO_HDR); + len -= sizeof(WMI_OPT_RX_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG, + bih->bssid[4], bih->bssid[5])); + + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_cie.ie_chan = bih->channel; + A_ASSERT(bss->ni_buf != NULL); + memcpy(bss->ni_buf, buf, len); + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return 0; +} + + /* This event indicates inactivity timeout of a fatpipe(pstream) + * at the target + */ +static int +wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PSTREAM_TIMEOUT_EVENT *ev; + + if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { + return A_EINVAL; + } + + A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG)); + + ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap; + + /* When the pstream (fat pipe == AC) timesout, it means there were no + * thinStreams within this pstream & it got implicitly created due to + * data flow on this AC. We start the inactivity timer only for + * implicitly created pstream. Just reset the host state. + */ + /* Set the activeTsids for this AC to 0 */ + LOCK_WMI(wmip); + wmip->wmi_streamExistsForAC[ev->trafficClass]=0; + wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass); + UNLOCK_WMI(wmip); + + /*Indicate inactivity to driver layer for this fatpipe (pstream)*/ + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass); + + return 0; +} + +static int +wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_BIT_RATE_REPLY *reply; + s32 rate; + u32 sgi,index; + /* 54149: + * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY. + * since there is difference in the length and to avoid returning + * error value. + */ + if (len < sizeof(WMI_BIT_RATE_REPLY)) { + return A_EINVAL; + } + reply = (WMI_BIT_RATE_REPLY *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); + + if (reply->rateIndex == (s8) RATE_AUTO) { + rate = RATE_AUTO; + } else { + // the SGI state is stored as the MSb of the rateIndex + index = reply->rateIndex & 0x7f; + sgi = (reply->rateIndex & 0x80)? 1:0; + rate = wmi_rateTable[index][sgi]; + } + + A_WMI_BITRATE_RX(wmip->wmi_devt, rate); + return 0; +} + +static int +wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_FIX_RATES_REPLY *reply; + + if (len < sizeof(WMI_FIX_RATES_REPLY)) { + return A_EINVAL; + } + reply = (WMI_FIX_RATES_REPLY *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask)); + + A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask); + + return 0; +} + +static int +wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CHANNEL_LIST_REPLY *reply; + + if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_CHANNEL_LIST_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels, + reply->channelList); + + return 0; +} + +static int +wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TX_PWR_REPLY *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TX_PWR_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM); + + return 0; +} +static int +wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_GET_KEEPALIVE_CMD *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_GET_KEEPALIVE_CMD *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured); + + return 0; +} + + +static int +wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETOPENREQ_EVENT *dsetopenreq; + + if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) { + return A_EINVAL; + } + dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id)); + A_WMI_DSET_OPEN_REQ(wmip->wmi_devt, + dsetopenreq->dset_id, + dsetopenreq->targ_dset_handle, + dsetopenreq->targ_reply_fn, + dsetopenreq->targ_reply_arg); + + return 0; +} + +#ifdef CONFIG_HOST_DSET_SUPPORT +static int +wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETCLOSE_EVENT *dsetclose; + + if (len < sizeof(WMIX_DSETCLOSE_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetclose = (WMIX_DSETCLOSE_EVENT *)datap; + A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie); + + return 0; +} + +static int +wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETDATAREQ_EVENT *dsetdatareq; + + if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap; + A_WMI_DSET_DATA_REQ(wmip->wmi_devt, + dsetdatareq->access_cookie, + dsetdatareq->offset, + dsetdatareq->length, + dsetdatareq->targ_buf, + dsetdatareq->targ_reply_fn, + dsetdatareq->targ_reply_arg); + + return 0; +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +static int +wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_SCAN_COMPLETE_EVENT *ev; + + ev = (WMI_SCAN_COMPLETE_EVENT *)datap; + if ((int)ev->status == 0) { + wlan_refresh_inactive_nodes(&wmip->wmi_scan_table); + } + A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status); + is_probe_ssid = false; + + return 0; +} + +/* + * Target is reporting a programming error. This is for + * developer aid only. Target only checks a few common violations + * and it is responsibility of host to do all error checking. + * Behavior of target after wmi error event is undefined. + * A reset is recommended. + */ +static int +wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CMD_ERROR_EVENT *ev; + + ev = (WMI_CMD_ERROR_EVENT *)datap; + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId)); + switch (ev->errorCode) { + case (INVALID_PARAM): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n")); + break; + case (ILLEGAL_STATE): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n")); + break; + case (INTERNAL_ERROR): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n")); + break; + } + + return 0; +} + + +static int +wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len); + + return 0; +} + +static int +wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_RSSI_THRESHOLD_EVENT *reply; + WMI_RSSI_THRESHOLD_VAL newThreshold; + WMI_RSSI_THRESHOLD_PARAMS_CMD cmd; + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; + u8 upper_rssi_threshold, lower_rssi_threshold; + s16 rssi; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range; + rssi = reply->rssi; + + /* + * Identify the threshold breached and communicate that to the app. After + * that install a new set of thresholds based on the signal quality + * reported by the target + */ + if (newThreshold) { + /* Upper threshold breached */ + if (rssi < sq_thresh->upper_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: " + " %d\n", DBGARG, rssi)); + } else if ((rssi < sq_thresh->upper_threshold[1]) && + (rssi >= sq_thresh->upper_threshold[0])) + { + newThreshold = WMI_RSSI_THRESHOLD1_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[2]) && + (rssi >= sq_thresh->upper_threshold[1])) + { + newThreshold = WMI_RSSI_THRESHOLD2_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[3]) && + (rssi >= sq_thresh->upper_threshold[2])) + { + newThreshold = WMI_RSSI_THRESHOLD3_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[4]) && + (rssi >= sq_thresh->upper_threshold[3])) + { + newThreshold = WMI_RSSI_THRESHOLD4_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[5]) && + (rssi >= sq_thresh->upper_threshold[4])) + { + newThreshold = WMI_RSSI_THRESHOLD5_ABOVE; + } else if (rssi >= sq_thresh->upper_threshold[5]) { + newThreshold = WMI_RSSI_THRESHOLD6_ABOVE; + } + } else { + /* Lower threshold breached */ + if (rssi > sq_thresh->lower_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: " + "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0])); + } else if ((rssi > sq_thresh->lower_threshold[1]) && + (rssi <= sq_thresh->lower_threshold[0])) + { + newThreshold = WMI_RSSI_THRESHOLD6_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[2]) && + (rssi <= sq_thresh->lower_threshold[1])) + { + newThreshold = WMI_RSSI_THRESHOLD5_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[3]) && + (rssi <= sq_thresh->lower_threshold[2])) + { + newThreshold = WMI_RSSI_THRESHOLD4_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[4]) && + (rssi <= sq_thresh->lower_threshold[3])) + { + newThreshold = WMI_RSSI_THRESHOLD3_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[5]) && + (rssi <= sq_thresh->lower_threshold[4])) + { + newThreshold = WMI_RSSI_THRESHOLD2_BELOW; + } else if (rssi <= sq_thresh->lower_threshold[5]) { + newThreshold = WMI_RSSI_THRESHOLD1_BELOW; + } + } + /* Calculate and install the next set of thresholds */ + lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh, + sq_thresh->upper_threshold_valid_count); + /* Issue a wmi command to install the thresholds */ + cmd.thresholdAbove1_Val = upper_rssi_threshold; + cmd.thresholdBelow1_Val = lower_rssi_threshold; + cmd.weight = sq_thresh->weight; + cmd.pollTime = sq_thresh->polling_interval; + + rssi_event_value = rssi; + + if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n", + DBGARG)); + } + + A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi); + + return 0; +} + + +static int +wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ERROR_REPORT_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal); + + return 0; +} + +static int +wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CAC_EVENT *reply; + WMM_TSPEC_IE *tspec_ie; + u16 activeTsids; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_CAC_EVENT *)datap; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && + (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) { + tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); + + wmi_delete_pstream_cmd(wmip, reply->ac, + (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); + } + else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { + u8 i; + + /* following assumes that there is only one outstanding ADDTS request + when this event is received */ + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; + UNLOCK_WMI(wmip); + + for (i = 0; i < sizeof(activeTsids) * 8; i++) { + if ((activeTsids >> i) & 1) { + break; + } + } + if (i < (sizeof(activeTsids) * 8)) { + wmi_delete_pstream_cmd(wmip, reply->ac, i); + } + } + /* + * Ev#72990: Clear active tsids and Add missing handling + * for delete qos stream from AP + */ + else if (reply->cac_indication == CAC_INDICATION_DELETE) { + u8 tsid = 0; + + tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); + tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); + LOCK_WMI(wmip); + wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<wmi_streamExistsForAC[reply->ac]; + UNLOCK_WMI(wmip); + + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if (!activeTsids) { + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac); + wmip->wmi_fatPipeExists &= ~(1 << reply->ac); + } + } + + A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, + reply->cac_indication, reply->statusCode, + reply->tspecSuggestion); + + return 0; +} + +static int +wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CHANNEL_CHANGE_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_CHANNEL_CHANGE_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel, + reply->newChannel); + + return 0; +} + +static int +wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_HB_CHALLENGE_RESP_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG)); + + A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source); + + return 0; +} + +static int +wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ROAM_TBL *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_TBL *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply); + + return 0; +} + +static int +wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ROAM_DATA *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_DATA *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply); + + return 0; +} + +static int +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt); + + return 0; +} + +static int +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_SNR_THRESHOLD_EVENT *reply; + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; + WMI_SNR_THRESHOLD_VAL newThreshold; + WMI_SNR_THRESHOLD_PARAMS_CMD cmd; + u8 upper_snr_threshold, lower_snr_threshold; + s16 snr; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_SNR_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range; + snr = reply->snr; + /* + * Identify the threshold breached and communicate that to the app. After + * that install a new set of thresholds based on the signal quality + * reported by the target + */ + if (newThreshold) { + /* Upper threshold breached */ + if (snr < sq_thresh->upper_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: " + "%d\n", DBGARG, snr)); + } else if ((snr < sq_thresh->upper_threshold[1]) && + (snr >= sq_thresh->upper_threshold[0])) + { + newThreshold = WMI_SNR_THRESHOLD1_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[2]) && + (snr >= sq_thresh->upper_threshold[1])) + { + newThreshold = WMI_SNR_THRESHOLD2_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[3]) && + (snr >= sq_thresh->upper_threshold[2])) + { + newThreshold = WMI_SNR_THRESHOLD3_ABOVE; + } else if (snr >= sq_thresh->upper_threshold[3]) { + newThreshold = WMI_SNR_THRESHOLD4_ABOVE; + } + } else { + /* Lower threshold breached */ + if (snr > sq_thresh->lower_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: " + "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0])); + } else if ((snr > sq_thresh->lower_threshold[1]) && + (snr <= sq_thresh->lower_threshold[0])) + { + newThreshold = WMI_SNR_THRESHOLD4_BELOW; + } else if ((snr > sq_thresh->lower_threshold[2]) && + (snr <= sq_thresh->lower_threshold[1])) + { + newThreshold = WMI_SNR_THRESHOLD3_BELOW; + } else if ((snr > sq_thresh->lower_threshold[3]) && + (snr <= sq_thresh->lower_threshold[2])) + { + newThreshold = WMI_SNR_THRESHOLD2_BELOW; + } else if (snr <= sq_thresh->lower_threshold[3]) { + newThreshold = WMI_SNR_THRESHOLD1_BELOW; + } + } + + /* Calculate and install the next set of thresholds */ + lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh, + sq_thresh->upper_threshold_valid_count); + + /* Issue a wmi command to install the thresholds */ + cmd.thresholdAbove1_Val = upper_snr_threshold; + cmd.thresholdBelow1_Val = lower_snr_threshold; + cmd.weight = sq_thresh->weight; + cmd.pollTime = sq_thresh->polling_interval; + + A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n" + ,DBGARG, snr, newThreshold, lower_snr_threshold, + upper_snr_threshold)); + + snr_event_value = snr; + + if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n", + DBGARG)); + } + A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr); + + return 0; +} + +static int +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_LQ_THRESHOLD_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_LQ_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, + (WMI_LQ_THRESHOLD_VAL) reply->range, + reply->lq); + + return 0; +} + +static int +wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + u16 ap_info_entry_size; + WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap; + WMI_AP_INFO_V1 *ap_info_v1; + u8 i; + + if (len < sizeof(WMI_APLIST_EVENT)) { + return A_EINVAL; + } + + if (ev->apListVer == APLIST_VER1) { + ap_info_entry_size = sizeof(WMI_AP_INFO_V1); + ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList; + } else { + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP)); + if (len < (int)(sizeof(WMI_APLIST_EVENT) + + (ev->numAP - 1) * ap_info_entry_size)) + { + return A_EINVAL; + } + + /* + * AP List Ver1 Contents + */ + for (i = 0; i < ev->numAP; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\ + "Channel %d\n", i, + ap_info_v1->bssid[0], ap_info_v1->bssid[1], + ap_info_v1->bssid[2], ap_info_v1->bssid[3], + ap_info_v1->bssid[4], ap_info_v1->bssid[5], + ap_info_v1->channel)); + ap_info_v1++; + } + return 0; +} + +static int +wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + u32 dropped; + + dropped = *((u32 *)datap); + datap += sizeof(dropped); + len -= sizeof(dropped); + A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len); + return 0; +} + +/* + * Called to send a wmi command. Command specific data is already built + * on osbuf and current osbuf->data points to it. + */ +int +wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ + int status; +#define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID)) + WMI_CMD_HDR *cHdr; + HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id; + + A_ASSERT(osbuf != NULL); + + if (syncflag >= END_WMIFLAG) { + A_NETBUF_FREE(osbuf); + return A_EINVAL; + } + + if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all data currently queued is transmitted before + * the cmd execution. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + return A_NO_MEMORY; + } + + cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = (u16) cmdId; + cHdr->info1 = 0; // added for virtual interface + + /* + * Only for OPT_TX_CMD, use BE endpoint. + */ + if (IS_OPT_TX_CMD(cmdId)) { + if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) { + A_NETBUF_FREE(osbuf); + return status; + } + eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE); + } + A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid); + + if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all new data queued waits for the command to + * execute. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + return (0); +#undef IS_OPT_TX_CMD +} + +int +wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ + WMIX_CMD_HDR *cHdr; + + if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + return A_NO_MEMORY; + } + + cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = (u32) cmdId; + + return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag); +} + +int +wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType, + DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode, + CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen, + CRYPTO_TYPE groupCrypto, u8 groupCryptoLen, + int ssidLength, u8 *ssid, + u8 *bssid, u16 channel, u32 ctrl_flags) +{ + void *osbuf; + WMI_CONNECT_CMD *cc; + wmip->wmi_traffic_class = 100; + + if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) { + return A_EINVAL; + } + if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD)); + + cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + if (ssidLength) + { + memcpy(cc->ssid, ssid, ssidLength); + } + + cc->ssidLength = ssidLength; + cc->networkType = netType; + cc->dot11AuthMode = dot11AuthMode; + cc->authMode = authMode; + cc->pairwiseCryptoType = pairwiseCrypto; + cc->pairwiseCryptoLen = pairwiseCryptoLen; + cc->groupCryptoType = groupCrypto; + cc->groupCryptoLen = groupCryptoLen; + cc->channel = channel; + cc->ctrl_flags = ctrl_flags; + + if (bssid != NULL) { + memcpy(cc->bssid, bssid, ATH_MAC_LEN); + } + + wmip->wmi_pair_crypto_type = pairwiseCrypto; + wmip->wmi_grp_crypto_type = groupCrypto; + + return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel) +{ + void *osbuf; + WMI_RECONNECT_CMD *cc; + wmip->wmi_traffic_class = 100; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD)); + + cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + cc->channel = channel; + + if (bssid != NULL) { + memcpy(cc->bssid, bssid, ATH_MAC_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_disconnect_cmd(struct wmi_t *wmip) +{ + int status; + wmip->wmi_traffic_class = 100; + + /* Bug fix for 24817(elevator bug) - the disconnect command does not + need to do a SYNC before.*/ + status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID); + + return status; +} + +int +wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, + u32 forceFgScan, u32 isLegacy, + u32 homeDwellTime, u32 forceScanInterval, + s8 numChan, u16 *channelList) +{ + void *osbuf; + WMI_START_SCAN_CMD *sc; + s8 size; + + size = sizeof (*sc); + + if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { + return A_EINVAL; + } + + if (numChan) { + if (numChan > WMI_MAX_CHANNELS) { + return A_EINVAL; + } + size += sizeof(u16) * (numChan - 1); + } + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); + sc->scanType = scanType; + sc->forceFgScan = forceFgScan; + sc->isLegacy = isLegacy; + sc->homeDwellTime = homeDwellTime; + sc->forceScanInterval = forceScanInterval; + sc->numChannels = numChan; + if (numChan) { + memcpy(sc->channelList, channelList, numChan * sizeof(u16)); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, u16 maxact_chdw_msec, + u16 pas_chdw_msec, + u8 shScanRatio, u8 scanCtrlFlags, + u32 max_dfsch_act_time, u16 maxact_scan_per_ssid) +{ + void *osbuf; + WMI_SCAN_PARAMS_CMD *sc; + + osbuf = A_NETBUF_ALLOC(sizeof(*sc)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*sc)); + + sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(sc, sizeof(*sc)); + sc->fg_start_period = fg_start_sec; + sc->fg_end_period = fg_end_sec; + sc->bg_period = bg_sec; + sc->minact_chdwell_time = minact_chdw_msec; + sc->maxact_chdwell_time = maxact_chdw_msec; + sc->pas_chdwell_time = pas_chdw_msec; + sc->shortScanRatio = shScanRatio; + sc->scanCtrlFlags = scanCtrlFlags; + sc->max_dfsch_act_time = max_dfsch_act_time; + sc->maxact_scan_per_ssid = maxact_scan_per_ssid; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask) +{ + void *osbuf; + WMI_BSS_FILTER_CMD *cmd; + + if (filter >= LAST_BSS_FILTER) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bssFilter = filter; + cmd->ieMask = ieMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag, + u8 ssidLength, u8 *ssid) +{ + void *osbuf; + WMI_PROBED_SSID_CMD *cmd; + + if (index > MAX_PROBED_SSID_INDEX) { + return A_EINVAL; + } + if (ssidLength > sizeof(cmd->ssid)) { + return A_EINVAL; + } + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) { + return A_EINVAL; + } + if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) { + return A_EINVAL; + } + + if (flag & SPECIFIC_SSID_FLAG) { + is_probe_ssid = true; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->entryIndex = index; + cmd->flag = flag; + cmd->ssidLength = ssidLength; + memcpy(cmd->ssid, ssid, ssidLength); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons) +{ + void *osbuf; + WMI_LISTEN_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->listenInterval = listenInterval; + cmd->numBeacons = listenBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons) +{ + void *osbuf; + WMI_BMISS_TIME_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bmissTime = bmissTime; + cmd->numBeacons = bmissBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType, + u8 ieLen, u8 *ieInfo) +{ + void *osbuf; + WMI_SET_ASSOC_INFO_CMD *cmd; + u16 cmdLen; + + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + cmd->ieType = ieType; + cmd->bufferSize = ieLen; + memcpy(cmd->assocInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode) +{ + void *osbuf; + WMI_POWER_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->powerMode = powerMode; + wmip->wmi_powerMode = powerMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl, + u16 atim_windows, u16 timeout_value) +{ + void *osbuf; + WMI_IBSS_PM_CAPS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->power_saving = pmEnable; + cmd->ttl = ttl; + cmd->atim_windows = atim_windows; + cmd->timeout_value = timeout_value; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time, + u32 ps_period, u8 sleep_period) +{ + void *osbuf; + WMI_AP_PS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->psType = psType; + cmd->idle_time = idle_time; + cmd->ps_period = ps_period; + cmd->sleep_period = sleep_period; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod, + u16 psPollNum, u16 dtimPolicy, + u16 tx_wakeup_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy) +{ + void *osbuf; + WMI_POWER_PARAMS_CMD *pm; + + osbuf = A_NETBUF_ALLOC(sizeof(*pm)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*pm)); + + pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(pm, sizeof(*pm)); + pm->idle_period = idlePeriod; + pm->pspoll_number = psPollNum; + pm->dtim_policy = dtimPolicy; + pm->tx_wakeup_policy = tx_wakeup_policy; + pm->num_tx_to_wakeup = num_tx_to_wakeup; + pm->ps_fail_event_policy = ps_fail_event_policy; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout) +{ + void *osbuf; + WMI_DISC_TIMEOUT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->disconnectTimeout = timeout; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType, + u8 keyUsage, u8 keyLength, u8 *keyRSC, + u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr, + WMI_SYNC_FLAG sync_flag) +{ + void *osbuf; + WMI_ADD_CIPHER_KEY_CMD *cmd; + + if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) || + (keyMaterial == NULL)) + { + return A_EINVAL; + } + + if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + cmd->keyType = keyType; + cmd->keyUsage = keyUsage; + cmd->keyLength = keyLength; + memcpy(cmd->key, keyMaterial, keyLength); +#ifdef WAPI_ENABLE + if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) { +#else + if (NULL != keyRSC) { +#endif // WAPI_ENABLE + memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); + } + cmd->key_op_ctrl = key_op_ctrl; + + if(macAddr) { + memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag)); +} + +int +wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk) +{ + void *osbuf; + WMI_ADD_KRK_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd->krk, krk, WMI_KRK_LEN); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_krk_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID); +} + +int +wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex) +{ + void *osbuf; + WMI_DELETE_CIPHER_KEY_CMD *cmd; + + if (keyIndex > WMI_MAX_KEY_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId, + bool set) +{ + void *osbuf; + WMI_SET_PMKID_CMD *cmd; + + if (bssid == NULL) { + return A_EINVAL; + } + + if ((set == true) && (pmkId == NULL)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + if (set == true) { + memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid)); + cmd->enable = PMKID_ENABLE; + } else { + A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid)); + cmd->enable = PMKID_DISABLE; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en) +{ + void *osbuf; + WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_akmp_params_cmd(struct wmi_t *wmip, + WMI_SET_AKMP_PARAMS_CMD *akmpParams) +{ + void *osbuf; + WMI_SET_AKMP_PARAMS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->akmpInfo = akmpParams->akmpInfo; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_pmkid_list_cmd(struct wmi_t *wmip, + WMI_SET_PMKID_LIST_CMD *pmkInfo) +{ + void *osbuf; + WMI_SET_PMKID_LIST_CMD *cmd; + u16 cmdLen; + u8 i; + + cmdLen = sizeof(pmkInfo->numPMKID) + + pmkInfo->numPMKID * sizeof(WMI_PMKID); + + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->numPMKID = pmkInfo->numPMKID; + + for (i = 0; i < cmd->numPMKID; i++) { + memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i], + WMI_PMKID_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_pmkid_list_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID); +} + +int +wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid) +{ + WMI_DATA_HDR *dtHdr; + + A_ASSERT( eid != wmip->wmi_endpoint_id); + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + dtHdr->info = + (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT; + + dtHdr->info3 = 0; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid)); + + return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid)); +} + +typedef struct _WMI_DATA_SYNC_BUFS { + u8 trafficClass; + void *osbuf; +}WMI_DATA_SYNC_BUFS; + +static int +wmi_sync_point(struct wmi_t *wmip) +{ + void *cmd_osbuf; + WMI_SYNC_CMD *cmd; + WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; + u8 i,numPriStreams=0; + int status = 0; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + memset(dataSyncBufs,0,sizeof(dataSyncBufs)); + + /* lock out while we walk through the priority list and assemble our local array */ + LOCK_WMI(wmip); + + for (i=0; i < WMM_NUM_AC ; i++) { + if (wmip->wmi_fatPipeExists & (1 << i)) { + numPriStreams++; + dataSyncBufs[numPriStreams-1].trafficClass = i; + } + } + + UNLOCK_WMI(wmip); + + /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */ + + do { + /* + * We allocate all network buffers needed so we will be able to + * send all required frames. + */ + cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (cmd_osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + + A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd)); + + cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + /* In the SYNC cmd sent on the control Ep, send a bitmap of the data + * eps on which the Data Sync will be sent + */ + cmd->dataSyncMap = wmip->wmi_fatPipeExists; + + for (i=0; i < numPriStreams ; i++) { + dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0); + if (dataSyncBufs[i].osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + } //end for + + /* if Buffer allocation for any of the dataSync fails, then do not + * send the Synchronize cmd on the control ep + */ + if (status) { + break; + } + + /* + * Send sync cmd followed by sync data messages on all endpoints being + * used + */ + status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID, + NO_SYNC_WMIFLAG); + + if (status) { + break; + } + /* cmd buffer sent, we no longer own it */ + cmd_osbuf = NULL; + + for(i=0; i < numPriStreams; i++) { + A_ASSERT(dataSyncBufs[i].osbuf != NULL); + status = wmi_dataSync_send(wmip, + dataSyncBufs[i].osbuf, + A_WMI_Ac2EndpointID(wmip->wmi_devt, + dataSyncBufs[i]. + trafficClass) + ); + + if (status) { + break; + } + /* we don't own this buffer anymore, NULL it out of the array so it + * won't get cleaned up */ + dataSyncBufs[i].osbuf = NULL; + } //end for + + } while(false); + + /* free up any resources left over (possibly due to an error) */ + + if (cmd_osbuf != NULL) { + A_NETBUF_FREE(cmd_osbuf); + } + + for (i = 0; i < numPriStreams; i++) { + if (dataSyncBufs[i].osbuf != NULL) { + A_NETBUF_FREE(dataSyncBufs[i].osbuf); + } + } + + return (status); +} + +int +wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params) +{ + void *osbuf; + WMI_CREATE_PSTREAM_CMD *cmd; + u8 fatPipeExistsForAC=0; + s32 minimalPHY = 0; + s32 nominalPHY = 0; + + /* Validate all the parameters. */ + if( !((params->userPriority < 8) && + (params->userPriority <= 0x7) && + (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) && + (params->trafficDirection == UPLINK_TRAFFIC || + params->trafficDirection == DNLINK_TRAFFIC || + params->trafficDirection == BIDIR_TRAFFIC) && + (params->trafficType == TRAFFIC_TYPE_APERIODIC || + params->trafficType == TRAFFIC_TYPE_PERIODIC ) && + (params->voicePSCapability == DISABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_ALL_AC) && + (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) ) + { + return A_EINVAL; + } + + // + // check nominal PHY rate is >= minimalPHY, so that DUT + // can allow TSRS IE + // + + // get the physical rate + minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps + + // check minimal phy < nominal phy rate + // + if (params->nominalPHY >= minimalPHY) + { + nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps + A_DPRINTF(DBG_WMI, + (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG, + minimalPHY, nominalPHY)); + + params->nominalPHY = nominalPHY; + } + else + { + params->nominalPHY = 0; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + A_DPRINTF(DBG_WMI, + (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG, + params->trafficClass, params->tsid)); + + cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd, params, sizeof(*cmd)); + + /* this is an implicitly created Fat pipe */ + if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) { + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } else { + /* this is an explicitly created thin stream within a fat pipe */ + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<tsid); + /* if a thinstream becomes active, the fat pipe automatically + * becomes active + */ + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } + + /* Indicate activty change to driver layer only if this is the + * first TSID to get created in this AC explicitly or an implicit + * fat pipe is getting created. + */ + if (!fatPipeExistsForAC) { + A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass); + } + + /* mike: should be SYNC_BEFORE_WMIFLAG */ + return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid) +{ + void *osbuf; + WMI_DELETE_PSTREAM_CMD *cmd; + int status; + u16 activeTsids=0; + + /* validate the parameters */ + if (trafficClass > 3) { + A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass)); + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->trafficClass = trafficClass; + cmd->tsid = tsid; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + /* Check if the tsid was created & exists */ + if (!(activeTsids & (1<wmi_streamExistsForAC[trafficClass] &= ~(1<wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if(!activeTsids) { + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass); + wmip->wmi_fatPipeExists &= ~(1< 15)){ + + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + frameType = (u8)((subType << 4) | type); + + cmd->bEnableMask = bEnable; + cmd->frameType = frameType; + cmd->frameRateMask = rateMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * used to set the bit rate. rate is in Kbps. If rate == -1 + * then auto selection is used. + */ +int +wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate) +{ + void *osbuf; + WMI_BIT_RATE_CMD *cmd; + s8 drix, mrix, crix, ret_val; + + if (dataRate != -1) { + ret_val = wmi_validate_bitrate(wmip, dataRate, &drix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + drix = -1; + } + + if (mgmtRate != -1) { + ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + mrix = -1; + } + if (ctlRate != -1) { + ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + crix = -1; + } + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->rateIndex = drix; + cmd->mgmtRateIndex = mrix; + cmd->ctlRateIndex = crix; + + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_bitrate_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID); +} + +/* + * Returns true iff the given rate index is legal in the current PHY mode. + */ +bool +wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex) +{ + WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode; + bool isValid = true; + switch(phyMode) { + case WMI_11A_MODE: + if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){ + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + + case WMI_11B_MODE: + if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) { + isValid = false; + } + break; + + case WMI_11GONLY_MODE: + if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + + case WMI_11G_MODE: + case WMI_11AG_MODE: + if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + default: + A_ASSERT(false); + break; + } + + return isValid; +} + +s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx) +{ + s8 i; + + for (i=0;;i++) + { + if (wmi_rateTable[(u32) i][0] == 0) { + return A_EINVAL; + } + if (wmi_rateTable[(u32) i][0] == rate) { + break; + } + } + + if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) { + return A_EINVAL; + } + + *rate_idx = i; + return 0; +} + +int +wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask) +{ + void *osbuf; + WMI_FIX_RATES_CMD *cmd; +#if 0 + s32 rateIndex; +/* This check does not work for AR6003 as the HT modes are enabled only when + * the STA is connected to a HT_BSS and is not based only on channel. It is + * safe to skip this check however because rate control will only use rates + * that are permitted by the valid rate mask and the fix rate mask. Meaning + * the fix rate mask is not sufficient by itself to cause an invalid rate + * to be used. */ + /* Make sure all rates in the mask are valid in the current PHY mode */ + for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) { + if((1 << rateIndex) & (u32)fixRatesMask) { + if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) { + A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG)); + return A_EINVAL; + } + } + } +#endif + + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->fixRateMask = fixRatesMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_ratemask_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID); +} + +int +wmi_get_channelList_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID); +} + +/* + * used to generate a wmi sey channel Parameters cmd. + * mode should always be specified and corresponds to the phy mode of the + * wlan. + * numChan should alway sbe specified. If zero indicates that all available + * channels should be used. + * channelList is an array of channel frequencies (in Mhz) which the radio + * should limit its operation to. It should be NULL if numChan == 0. Size of + * array should correspond to numChan entries. + */ +int +wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam, + WMI_PHY_MODE mode, s8 numChan, + u16 *channelList) +{ + void *osbuf; + WMI_CHANNEL_PARAMS_CMD *cmd; + s8 size; + + size = sizeof (*cmd); + + if (numChan) { + if (numChan > WMI_MAX_CHANNELS) { + return A_EINVAL; + } + size += sizeof(u16) * (numChan - 1); + } + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + wmip->wmi_phyMode = mode; + cmd->scanParam = scanParam; + cmd->phyMode = mode; + cmd->numChannels = numChan; + memcpy(cmd->channelList, channelList, numChan * sizeof(u16)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +void +wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; + /* + * Parse the command and store the threshold values here. The checks + * for valid values can be put here + */ + sq_thresh->weight = rssiCmd->weight; + sq_thresh->polling_interval = rssiCmd->pollTime; + + sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold_valid_count = 6; + + /* List sorted in descending order */ + sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold_valid_count = 6; + + if (!rssi_event_value) { + /* + * Configuring the thresholds to their extremes allows the host to get an + * event from the target which is used for the configuring the correct + * thresholds + */ + rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0]; + rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0]; + } else { + /* + * In case the user issues multiple times of rssi_threshold_setting, + * we should not use the extreames anymore, the target does not expect that. + */ + rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh, + sq_thresh->upper_threshold_valid_count); + rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh, + sq_thresh->lower_threshold_valid_count); +} +} + +int +wmi_set_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + + /* Check these values are in ascending order */ + if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val || + rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val || + rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val || + rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val || + rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val || + rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val || + rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val || + rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val || + rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val || + rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) + { + return A_EINVAL; + } + + wmi_cache_configure_rssithreshold(wmip, rssiCmd); + + return (wmi_send_rssi_threshold_params(wmip, rssiCmd)); +} + +int +wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd) +{ + void *osbuf; + WMI_SET_IP_CMD *cmd; + + /* Multicast address are not valid */ + if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) || + (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD)); + cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, + WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd) +{ + void *osbuf; + s8 size; + WMI_SET_HOST_SLEEP_MODE_CMD *cmd; + u16 activeTsids=0; + u8 streamExists=0; + u8 i; + + if( hostModeCmd->awake == hostModeCmd->asleep) { + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD)); + + if(hostModeCmd->asleep) { + /* + * Relinquish credits from all implicitly created pstreams since when we + * go to sleep. If user created explicit thinstreams exists with in a + * fatpipe leave them intact for the user to delete + */ + LOCK_WMI(wmip); + streamExists = wmip->wmi_fatPipeExists; + UNLOCK_WMI(wmip); + + for(i=0;i< WMM_NUM_AC;i++) { + if (streamExists & (1<wmi_streamExistsForAC[i]; + UNLOCK_WMI(wmip); + /* If there are no user created thin streams delete the fatpipe */ + if(!activeTsids) { + streamExists &= ~(1<wmi_devt,i); + } + } + } + + /* Update the fatpipes that exists*/ + LOCK_WMI(wmip); + wmip->wmi_fatPipeExists = streamExists; + UNLOCK_WMI(wmip); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_wow_mode_cmd(struct wmi_t *wmip, + WMI_SET_WOW_MODE_CMD *wowModeCmd) +{ + void *osbuf; + s8 size; + WMI_SET_WOW_MODE_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_wow_list_cmd(struct wmi_t *wmip, + WMI_GET_WOW_LIST_CMD *wowListCmd) +{ + void *osbuf; + s8 size; + WMI_GET_WOW_LIST_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID, + NO_SYNC_WMIFLAG)); + +} + +static int +wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_GET_WOW_LIST_REPLY *reply; + + if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_GET_WOW_LIST_REPLY *)datap; + + A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters, + reply); + + return 0; +} + +int wmi_add_wow_pattern_cmd(struct wmi_t *wmip, + WMI_ADD_WOW_PATTERN_CMD *addWowCmd, + u8 *pattern, u8 *mask, + u8 pattern_size) +{ + void *osbuf; + s8 size; + WMI_ADD_WOW_PATTERN_CMD *cmd; + u8 *filter_mask = NULL; + + size = sizeof (*cmd); + + size += ((2 * addWowCmd->filter_size)* sizeof(u8)); + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->filter_list_id = addWowCmd->filter_list_id; + cmd->filter_offset = addWowCmd->filter_offset; + cmd->filter_size = addWowCmd->filter_size; + + memcpy(cmd->filter, pattern, addWowCmd->filter_size); + + filter_mask = (u8 *)(cmd->filter + cmd->filter_size); + memcpy(filter_mask, mask, addWowCmd->filter_size); + + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_del_wow_pattern_cmd(struct wmi_t *wmip, + WMI_DEL_WOW_PATTERN_CMD *delWowCmd) +{ + void *osbuf; + s8 size; + WMI_DEL_WOW_PATTERN_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); + +} + +void +wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; + /* + * Parse the command and store the threshold values here. The checks + * for valid values can be put here + */ + sq_thresh->weight = snrCmd->weight; + sq_thresh->polling_interval = snrCmd->pollTime; + + sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val; + sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val; + sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val; + sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val; + sq_thresh->upper_threshold_valid_count = 4; + + /* List sorted in descending order */ + sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val; + sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val; + sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val; + sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val; + sq_thresh->lower_threshold_valid_count = 4; + + if (!snr_event_value) { + /* + * Configuring the thresholds to their extremes allows the host to get an + * event from the target which is used for the configuring the correct + * thresholds + */ + snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0]; + snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0]; + } else { + /* + * In case the user issues multiple times of snr_threshold_setting, + * we should not use the extreames anymore, the target does not expect that. + */ + snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh, + sq_thresh->upper_threshold_valid_count); + snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh, + sq_thresh->lower_threshold_valid_count); + } + +} +int +wmi_set_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val || + snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val || + snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val || + snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val || + snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val || + snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) + { + return A_EINVAL; + } + wmi_cache_configure_snrthreshold(wmip, snrCmd); + return (wmi_send_snr_threshold_params(wmip, snrCmd)); +} + +int +wmi_clr_rssi_snr(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(sizeof(int)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_lq_threshold_params(struct wmi_t *wmip, + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd) +{ + void *osbuf; + s8 size; + WMI_LQ_THRESHOLD_PARAMS_CMD *cmd; + /* These values are in ascending order */ + if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val || + lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val || + lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val || + lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val || + lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val || + lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) { + + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask) +{ + void *osbuf; + s8 size; + WMI_TARGET_ERROR_REPORT_BITMASK *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + cmd->bitmask = mask; + + return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source) +{ + void *osbuf; + WMIX_HB_CHALLENGE_RESP_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cookie = cookie; + cmd->source = source; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask, + u16 tsr, bool rep, u16 size, + u32 valid) +{ + void *osbuf; + WMIX_DBGLOG_CFG_MODULE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->config.cfgmmask = mmask; + cmd->config.cfgtsr = tsr; + cmd->config.cfgrep = rep; + cmd->config.cfgsize = size; + cmd->config.cfgvalid = valid; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_stats_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID); +} + +int +wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid) +{ + void *osbuf; + WMI_ADD_BAD_AP_CMD *cmd; + + if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG)); +} + +int +wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex) +{ + void *osbuf; + WMI_DELETE_BAD_AP_CMD *cmd; + + if (apIndex > WMI_MAX_BAD_AP_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_abort_scan_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID); +} + +int +wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM) +{ + void *osbuf; + WMI_SET_TX_PWR_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->dbM = dbM; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_txPwr_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID); +} + +u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass) +{ + u16 activeTsids=0; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + return activeTsids; +} + +int +wmi_get_roam_tbl_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID); +} + +int +wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType) +{ + void *osbuf; + u32 size = sizeof(u8); + WMI_TARGET_ROAM_DATA *cmd; + + osbuf = A_NETBUF_ALLOC(size); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf)); + cmd->roamDataType = roamDataType; + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, + u8 size) +{ + void *osbuf; + WMI_SET_ROAM_CTRL_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + memcpy(cmd, p, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_powersave_timers_cmd(struct wmi_t *wmip, + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, + u8 size) +{ + void *osbuf; + WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd; + + /* These timers can't be zero */ + if(!pCmd->psPollTimeout || !pCmd->triggerTimeout || + !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD || + pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) || + !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD || + pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD)) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + memcpy(cmd, pCmd, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin, + u8 eCWmax, u8 aifsn) +{ + void *osbuf; + WMI_SET_ACCESS_PARAMS_CMD *cmd; + + if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) || + (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC)) + { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->txop = txop; + cmd->eCWmin = eCWmin; + cmd->eCWmax = eCWmax; + cmd->aifsn = aifsn; + cmd->ac = ac; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType, + u8 trafficClass, u8 maxRetries, + u8 enableNotify) +{ + void *osbuf; + WMI_SET_RETRY_LIMITS_CMD *cmd; + + if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) && + (frameType != DATA_FRAMETYPE)) + { + return A_EINVAL; + } + + if (maxRetries > WMI_MAX_RETRIES) { + return A_EINVAL; + } + + if (frameType != DATA_FRAMETYPE) { + trafficClass = 0; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->frameType = frameType; + cmd->trafficClass = trafficClass; + cmd->maxRetries = maxRetries; + cmd->enableNotify = enableNotify; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID, + NO_SYNC_WMIFLAG)); +} + +void +wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid) +{ + if (bssid != NULL) { + memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN); + } +} + +int +wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode) +{ + void *osbuf; + WMI_SET_OPT_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->optMode = optMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID, + SYNC_BOTH_WMIFLAG)); +} + +int +wmi_opt_tx_frame_cmd(struct wmi_t *wmip, + u8 frmType, + u8 *dstMacAddr, + u8 *bssid, + u16 optIEDataLen, + u8 *optIEData) +{ + void *osbuf; + WMI_OPT_TX_FRAME_CMD *cmd; + osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd))); + + cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1)); + + cmd->frmType = frmType; + cmd->optIEDataLen = optIEDataLen; + //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd)); + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr)); + memcpy(&cmd->optIEData[0], optIEData, optIEDataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl) +{ + void *osbuf; + WMI_BEACON_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->beaconInterval = intvl; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize) +{ + void *osbuf; + WMI_SET_VOICE_PKT_SIZE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->voicePktSize = voicePktSize; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen) +{ + void *osbuf; + WMI_SET_MAX_SP_LEN_CMD *cmd; + + /* maxSPLen is a two-bit value. If user trys to set anything + * other than this, then its invalid + */ + if(maxSPLen & ~0x03) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->maxSPLen = maxSPLen; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID, + NO_SYNC_WMIFLAG)); +} + +u8 wmi_determine_userPriority( + u8 *pkt, + u32 layer2Pri) +{ + u8 ipPri; + iphdr *ipHdr = (iphdr *)pkt; + + /* Determine IPTOS priority */ + /* + * IP Tos format : + * (Refer Pg 57 WMM-test-plan-v1.2) + * IP-TOS - 8bits + * : DSCP(6-bits) ECN(2-bits) + * : DSCP - P2 P1 P0 X X X + * where (P2 P1 P0) form 802.1D + */ + ipPri = ipHdr->ip_tos >> 5; + ipPri &= 0x7; + + if ((layer2Pri & 0x7) > ipPri) + return ((u8)layer2Pri & 0x7); + else + return ipPri; +} + +u8 convert_userPriority_to_trafficClass(u8 userPriority) +{ + return (up_to_ac[userPriority & 0x7]); +} + +u8 wmi_get_power_mode_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_powerMode; +} + +int +wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance) +{ + int ret = 0; + +#define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0) +#define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0 +#define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0 +#define TSPEC_DELAY_BOUND_ATHEROS_DEF 0 +#define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0 +#define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */ + + /* Verify TSPEC params for ATHEROS compliance */ + if(tspecCompliance == ATHEROS_COMPLIANCE) { + if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) || + (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) || + (pCmd->minDataRate != pCmd->meanDataRate) || + (pCmd->minDataRate != pCmd->peakDataRate) || + (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) || + (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) || + (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) || + (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) { + + A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG)); + //A_PRINTF("%s: Invalid TSPEC params\n", __func__); + ret = A_EINVAL; + } + } + + return ret; +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static int +wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + ar6000_testmode_rx_report_event(wmip->wmi_devt, datap, len); + + return 0; +} + +#endif /* CONFIG_HOST_TCMD_SUPPORT*/ + +int +wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode) +{ + void *osbuf; + WMI_SET_AUTH_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode) +{ + void *osbuf; + WMI_SET_REASSOC_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy) +{ + void *osbuf; + WMI_SET_LPREAMBLE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + cmd->preamblePolicy = preamblePolicy; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold) +{ + void *osbuf; + WMI_SET_RTS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->threshold = threshold; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status) +{ + void *osbuf; + WMI_SET_WMM_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status) +{ + void *osbuf; + WMI_SET_QOS_SUPP_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg) +{ + void *osbuf; + WMI_SET_WMM_TXOP_CMD *cmd; + + if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) ) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->txopEnable = cfg; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_country(struct wmi_t *wmip, u8 *countryCode) +{ + void *osbuf; + WMI_AP_SET_COUNTRY_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd->countryCode,countryCode,3); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID, + NO_SYNC_WMIFLAG)); +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* WMI layer doesn't need to know the data type of the test cmd. + This would be beneficial for customers like Qualcomm, who might + have different test command requirements from different manufacturers + */ +int +wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len) +{ + void *osbuf; + char *data; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + osbuf= A_NETBUF_ALLOC(len); + if(osbuf == NULL) + { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, len); + data = A_NETBUF_DATA(osbuf); + memcpy(data, buf, len); + + return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID, + NO_SYNC_WMIFLAG)); +} + +#endif + +int +wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status) +{ + void *osbuf; + WMI_SET_BT_STATUS_CMD *cmd; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status)); + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->streamType = streamType; + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd) +{ + void *osbuf; + WMI_SET_BT_PARAMS_CMD* alloc_cmd; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType)); + + if (cmd->paramType == BT_PARAM_SCO) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger, + cmd->info.scoParams.dataResponseTimeout, + cmd->info.scoParams.stompScoRules, + cmd->info.scoParams.scoOptFlags, + cmd->info.scoParams.stompDutyCyleVal, + cmd->info.scoParams.stompDutyCyleMaxVal, + cmd->info.scoParams.psPollLatencyFraction, + cmd->info.scoParams.noSCOSlots, + cmd->info.scoParams.noIdleSlots, + cmd->info.scoParams.scoOptOffRssi, + cmd->info.scoParams.scoOptOnRssi, + cmd->info.scoParams.scoOptRtsCount)); + } + else if (cmd->paramType == BT_PARAM_A2DP) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit, + cmd->info.a2dpParams.a2dpBurstCntMin, + cmd->info.a2dpParams.a2dpDataRespTimeout, + cmd->info.a2dpParams.a2dpOptFlags, + cmd->info.a2dpParams.isCoLocatedBtRoleMaster, + cmd->info.a2dpParams.a2dpOptOffRssi, + cmd->info.a2dpParams.a2dpOptOnRssi, + cmd->info.a2dpParams.a2dpOptRtsCount)); + } + else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType)); + } + else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev)); + } + else if (cmd->paramType == BT_PARAM_ACLCOEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime, + cmd->info.aclCoexParams.aclBtMediumUsageTime, + cmd->info.aclCoexParams.aclDataRespTimeout)); + } + else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) { + A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG)); + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd, cmd, sizeof(*cmd)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID, + NO_SYNC_WMIFLAG)); + +} + + +int +wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); + A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_btcoex_stats_cmd(struct wmi_t *wmip) +{ + + return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID); + +} + +int +wmi_get_keepalive_configured(struct wmi_t *wmip) +{ + void *osbuf; + WMI_GET_KEEPALIVE_CMD *cmd; + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +u8 wmi_get_keepalive_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_keepaliveInterval; +} + +int +wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval) +{ + void *osbuf; + WMI_SET_KEEPALIVE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keepaliveInterval = keepaliveInterval; + wmip->wmi_keepaliveInterval = keepaliveInterval; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer) +{ + void *osbuf; + WMI_SET_PARAMS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd) + length); + + cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->opcode = opcode; + cmd->length = length; + memcpy(cmd->buffer, buffer, length); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) +{ + void *osbuf; + WMI_SET_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->multicast_mac[0] = 0x01; + cmd->multicast_mac[1] = 0x00; + cmd->multicast_mac[2] = 0x5e; + cmd->multicast_mac[3] = dot2&0x7F; + cmd->multicast_mac[4] = dot3; + cmd->multicast_mac[5] = dot4; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) +{ + void *osbuf; + WMI_SET_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->multicast_mac[0] = 0x01; + cmd->multicast_mac[1] = 0x00; + cmd->multicast_mac[2] = 0x5e; + cmd->multicast_mac[3] = dot2&0x7F; + cmd->multicast_mac[4] = dot3; + cmd->multicast_mac[5] = dot4; + + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable) +{ + void *osbuf; + WMI_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->enable = enable; + + return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen, + u8 *ieInfo) +{ + void *osbuf; + WMI_SET_APPIE_CMD *cmd; + u16 cmdLen; + + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + + cmd->mgmtFrmType = mgmtFrmType; + cmd->ieLen = ieLen; + memcpy(cmd->ieInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen) +{ + void *osbuf; + u8 *data; + + osbuf = A_NETBUF_ALLOC(dataLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, dataLen); + + data = A_NETBUF_DATA(osbuf); + + memcpy(data, cmd, dataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG)); +} + +s32 wmi_get_rate(s8 rateindex) +{ + if (rateindex == RATE_AUTO) { + return 0; + } else { + return(wmi_rateTable[(u32) rateindex][0]); + } +} + +void +wmi_node_return (struct wmi_t *wmip, bss_t *bss) +{ + if (NULL != bss) + { + wlan_node_return (&wmip->wmi_scan_table, bss); + } +} + +void +wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge) +{ + wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge); +} + +bss_t * +wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID) +{ + bss_t *node = NULL; + node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, + ssidLength, bIsWPA2, bMatchSSID); + return node; +} + + +#ifdef THREAD_X +void +wmi_refresh_scan_table (struct wmi_t *wmip) +{ + wlan_refresh_inactive_nodes (&wmip->wmi_scan_table); +} +#endif + +void +wmi_free_allnodes(struct wmi_t *wmip) +{ + wlan_free_allnodes(&wmip->wmi_scan_table); +} + +bss_t * +wmi_find_node(struct wmi_t *wmip, const u8 *macaddr) +{ + bss_t *ni=NULL; + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); + return ni; +} + +void +wmi_free_node(struct wmi_t *wmip, const u8 *macaddr) +{ + bss_t *ni=NULL; + + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); + if (ni != NULL) { + wlan_node_reclaim(&wmip->wmi_scan_table, ni); + } + + return; +} + +int +wmi_dset_open_reply(struct wmi_t *wmip, + u32 status, + u32 access_cookie, + u32 dset_size, + u32 dset_version, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETOPEN_REPLY_CMD *open_reply; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip)); + + osbuf = A_NETBUF_ALLOC(sizeof(*open_reply)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*open_reply)); + open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + open_reply->status = status; + open_reply->targ_dset_handle = targ_handle; + open_reply->targ_reply_fn = targ_reply_fn; + open_reply->targ_reply_arg = targ_reply_arg; + open_reply->access_cookie = access_cookie; + open_reply->size = dset_size; + open_reply->version = dset_version; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} + +static int +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) +{ + WMI_PMKID_LIST_REPLY *reply; + u32 expected_len; + + if (len < sizeof(WMI_PMKID_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_PMKID_LIST_REPLY *)datap; + expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN; + + if (len < expected_len) { + return A_EINVAL; + } + + A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID, + reply->pmkidList, reply->bssidList[0]); + + return 0; +} + + +static int +wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) +{ + WMI_SET_PARAMS_REPLY *reply; + + if (len < sizeof(WMI_SET_PARAMS_REPLY)) { + return A_EINVAL; + } + reply = (WMI_SET_PARAMS_REPLY *)datap; + + if (0 == reply->status) + { + + } + else + { + + } + + return 0; +} + + +#ifdef CONFIG_HOST_DSET_SUPPORT +int +wmi_dset_data_reply(struct wmi_t *wmip, + u32 status, + u8 *user_buf, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETDATA_REPLY_CMD *data_reply; + u32 size; + + size = sizeof(*data_reply) + length; + + if (size <= length) { + return A_ERROR; + } + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + data_reply->status = status; + data_reply->targ_buf = targ_buf; + data_reply->targ_reply_fn = targ_reply_fn; + data_reply->targ_reply_arg = targ_reply_arg; + data_reply->length = length; + + if (status == 0) { + if (a_copy_from_user(data_reply->buf, user_buf, length)) { + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +int +wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status) +{ + void *osbuf; + char *cmd; + + wps_enable = status; + + osbuf = a_netbuf_alloc(sizeof(1)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + a_netbuf_put(osbuf, sizeof(1)); + + cmd = (char *)(a_netbuf_to_data(osbuf)); + + A_MEMZERO(cmd, sizeof(*cmd)); + cmd[0] = (status?1:0); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +int +wmi_prof_cfg_cmd(struct wmi_t *wmip, + u32 period, + u32 nbins) +{ + void *osbuf; + WMIX_PROF_CFG_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->period = period; + cmd->nbins = nbins; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr) +{ + void *osbuf; + WMIX_PROF_ADDR_SET_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->addr = addr; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_prof_start_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID); +} + +int +wmi_prof_stop_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID); +} + +int +wmi_prof_count_get_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID); +} + +/* Called to handle WMIX_PROF_CONT_EVENTID */ +static int +wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG, + prof_data->addr, prof_data->count)); + + A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count); + + return 0; +} +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +#ifdef OS_ROAM_MANAGEMENT + +#define ETHERNET_MAC_ADDRESS_LENGTH 6 + +void +wmi_scan_indication (struct wmi_t *wmip) +{ + struct ieee80211_node_table *nt; + u32 gen; + u32 size; + u32 bsssize; + bss_t *bss; + u32 numbss; + PNDIS_802_11_BSSID_SCAN_INFO psi; + PBYTE pie; + NDIS_802_11_FIXED_IEs *pFixed; + NDIS_802_11_VARIABLE_IEs *pVar; + u32 RateSize; + + struct ar6kScanIndication + { + NDIS_802_11_STATUS_INDICATION ind; + NDIS_802_11_BSSID_SCAN_INFO_LIST slist; + } *pAr6kScanIndEvent; + + nt = &wmip->wmi_scan_table; + + ++nt->nt_si_gen; + + + gen = nt->nt_si_gen; + + size = offsetof(struct ar6kScanIndication, slist) + + offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo); + + numbss = 0; + + IEEE80211_NODE_LOCK(nt); + + //calc size + for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { + if (bss->ni_si_gen != gen) { + bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs); + bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); + +#ifdef SUPPORT_WPA2 + if (bss->ni_cie.ie_rsn) { + bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; + } +#endif + if (bss->ni_cie.ie_wpa) { + bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; + } + + // bsssize must be a multiple of 4 to maintain alignment. + bsssize = (bsssize + 3) & ~3; + + size += bsssize; + + numbss++; + } + } + + if (0 == numbss) + { +// RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n")); + ar6000_scan_indication (wmip->wmi_devt, NULL, 0); + IEEE80211_NODE_UNLOCK (nt); + return; + } + + pAr6kScanIndEvent = A_MALLOC(size); + + if (NULL == pAr6kScanIndEvent) + { + IEEE80211_NODE_UNLOCK(nt); + return; + } + + A_MEMZERO(pAr6kScanIndEvent, size); + + //copy data + pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList; + pAr6kScanIndEvent->slist.Version = 1; + pAr6kScanIndEvent->slist.NumItems = numbss; + + psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0]; + + for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { + if (bss->ni_si_gen != gen) { + + bss->ni_si_gen = gen; + + //Set scan time + psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC; + + // Copy data to bssid_ex + bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs); + bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); + +#ifdef SUPPORT_WPA2 + if (bss->ni_cie.ie_rsn) { + bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; + } +#endif + if (bss->ni_cie.ie_wpa) { + bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; + } + + // bsssize must be a multiple of 4 to maintain alignment. + bsssize = (bsssize + 3) & ~3; + + psi->Bssid.Length = bsssize; + + memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH); + + +//if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) || +// ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70))) +// RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5])); + + psi->Bssid.Ssid.SsidLength = 0; + pie = bss->ni_cie.ie_ssid; + + if (pie) { + // Format of SSID IE is: + // Type (1 octet) + // Length (1 octet) + // SSID (Length octets) + // + // Validation of the IE should have occurred within WMI. + // + if (pie[1] <= 32) { + psi->Bssid.Ssid.SsidLength = pie[1]; + memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength); + } + } + psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0; + + //Post the RSSI value relative to the Standard Noise floor value. + psi->Bssid.Rssi = bss->ni_rssi; + + if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) { + + if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) { + psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24; + } + else { + psi->Bssid.NetworkTypeInUse = Ndis802_11DS; + } + } + else { + psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5; + } + + psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration); + psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us) + psi->Bssid.Configuration.ATIMWindow = 0; + psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000; + psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS; + + RateSize = 0; + pie = bss->ni_cie.ie_rates; + if (pie) { + RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX; + memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize); + } + pie = bss->ni_cie.ie_xrates; + if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) { + memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2], + (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize)); + } + + // Copy the fixed IEs + psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs); + + pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs; + memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp)); + pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt; + pFixed->Capabilities = bss->ni_cie.ie_capInfo; + + // Copy selected variable IEs + + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs)); + +#ifdef SUPPORT_WPA2 + // Copy the WPAv2 IE + if (bss->ni_cie.ie_rsn) { + pie = bss->ni_cie.ie_rsn; + psi->Bssid.IELength += pie[1] + 2; + memcpy(pVar, pie, pie[1] + 2); + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); + } +#endif + // Copy the WPAv1 IE + if (bss->ni_cie.ie_wpa) { + pie = bss->ni_cie.ie_wpa; + psi->Bssid.IELength += pie[1] + 2; + memcpy(pVar, pie, pie[1] + 2); + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); + } + + // Advance buffer pointer + psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid)); + } + } + + IEEE80211_NODE_UNLOCK(nt); + +// wmi_free_allnodes(wmip); + +// RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss)); + + ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size); + + kfree(pAr6kScanIndEvent); +} +#endif + +u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8)sq_thresh->upper_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index ++) { + if (rssi < sq_thresh->upper_threshold[index]) { + threshold = (u8)sq_thresh->upper_threshold[index]; + break; + } + } + + return threshold; +} + +u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8)sq_thresh->lower_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index ++) { + if (rssi > sq_thresh->lower_threshold[index]) { + threshold = (u8)sq_thresh->lower_threshold[index]; + break; + } + } + + return threshold; +} +static int +wmi_send_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + void *osbuf; + s8 size; + WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} +static int +wmi_send_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + void *osbuf; + s8 size; + WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd) +{ + void *osbuf; + WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd, cmd, sizeof(*cmd)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID, + NO_SYNC_WMIFLAG)); +} + +bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id) +{ + wmi_get_current_bssid (wmip, id); + return wlan_node_remove (&wmip->wmi_scan_table, id); +} + +int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss) +{ + wlan_setup_node (&wmip->wmi_scan_table, bss, id); + return 0; +} + +static int +wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap; + + A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd); + + return 0; +} + + +static int +wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap; + + A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +static int +wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap; + + A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +int +wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len); + + return 0; +} + + +int +wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len); + + return 0; + +} + +static int +wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap; + A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +//// //// +//// AP mode functions //// +//// //// +//////////////////////////////////////////////////////////////////////////////// +/* + * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG + * + * When AR6K in AP mode, This command will be called after + * changing ssid, channel etc. It will pass the profile to + * target with a flag which will indicate which parameter changed, + * also if this flag is 0, there was no change in parametes, so + * commit cmd will not be sent to target. Without calling this IOCTL + * the changes will not take effect. + */ +int +wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p) +{ + void *osbuf; + WMI_CONNECT_CMD *cm; + + osbuf = A_NETBUF_ALLOC(sizeof(*cm)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cm)); + cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cm, sizeof(*cm)); + + memcpy(cm,p,sizeof(*cm)); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID + * + * This command will be used to enable/disable hidden ssid functioanlity of + * beacon. If it is enabled, ssid will be NULL in beacon. + */ +int +wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid) +{ + void *osbuf; + WMI_AP_HIDDEN_SSID_CMD *hs; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD)); + hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(hs, sizeof(*hs)); + + hs->hidden_ssid = hidden_ssid; + + A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid)); + return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA + * + * This command is used to limit max num of STA that can connect + * with this AP. This value should not exceed AP_MAX_NUM_STA (this + * is max num of STA supported by AP). Value was already validated + * in ioctl.c + */ +int +wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta) +{ + void *osbuf; + WMI_AP_SET_NUM_STA_CMD *ns; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD)); + ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(ns, sizeof(*ns)); + + ns->num_sta = num_sta; + + A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta)); + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC + * + * This command is used to send list of mac of STAs which will + * be allowed to connect with this AP. When this list is empty + * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. + */ +int +wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl) +{ + void *osbuf; + WMI_AP_ACL_MAC_CMD *a; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD)); + a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(a, sizeof(*a)); + memcpy(a,acl,sizeof(*acl)); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_MLME + * + * This command is used to send list of mac of STAs which will + * be allowed to connect with this AP. When this list is empty + * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. + */ +int +wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason) +{ + void *osbuf; + WMI_AP_SET_MLME_CMD *mlme; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD)); + mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(mlme, sizeof(*mlme)); + + mlme->cmd = cmd; + memcpy(mlme->mac, mac, ATH_MAC_LEN); + mlme->reason = reason; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG)); +} + +static int +wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PSPOLL_EVENT *ev; + + if (len < sizeof(WMI_PSPOLL_EVENT)) { + return A_EINVAL; + } + ev = (WMI_PSPOLL_EVENT *)datap; + + A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid); + return 0; +} + +static int +wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len) +{ + A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt); + return 0; +} + +#ifdef WAPI_ENABLE +static int +wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len) +{ + u8 *ev; + + if (len < 7) { + return A_EINVAL; + } + ev = (u8 *)datap; + + A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]); + return 0; +} +#endif + +int +wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag) +{ + WMI_AP_SET_PVB_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD)); + cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->aid = aid; + cmd->flag = flag; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period) +{ + WMI_AP_CONN_INACT_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD)); + cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->period = period; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell) +{ + WMI_AP_PROT_SCAN_TIME_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); + cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->period_min = period; + cmd->dwell_ms = dwell; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim) +{ + WMI_AP_SET_DTIM_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD)); + cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->dtim = dtim; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY + * + * This command is used to set ACL policay. While changing policy, if you + * want to retain the existing MAC addresses in the ACL list, policy should be + * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared. + * If there is no chage in policy, the list will be intact. + */ +int +wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy) +{ + void *osbuf; + WMI_AP_ACL_POLICY_CMD *po; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; +} + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD)); + po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(po, sizeof(*po)); + + po->policy = policy; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset) +{ + void *osbuf; + WMI_AP_SET_11BG_RATESET_CMD *rs; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD)); + rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(rs, sizeof(*rs)); + + rs->rateset = rateset; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd) +{ + void *osbuf; + WMI_SET_HT_CAP_CMD *htCap; + u8 band; + + osbuf = A_NETBUF_ALLOC(sizeof(*htCap)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*htCap)); + + band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ; + wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0; + + htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(htCap, sizeof(*htCap)); + memcpy(htCap, cmd, sizeof(*htCap)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width) +{ + void *osbuf; + WMI_SET_HT_OP_CMD *htInfo; + + osbuf = A_NETBUF_ALLOC(sizeof(*htInfo)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*htInfo)); + + htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(htInfo, sizeof(*htInfo)); + htInfo->sta_chan_width = sta_chan_width; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray) +{ + void *osbuf; + WMI_SET_TX_SELECT_RATES_CMD *pData; + + osbuf = A_NETBUF_ALLOC(sizeof(*pData)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*pData)); + + pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(pData, pMaskArray, sizeof(*pData)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz) +{ + void *osbuf; + WMI_HCI_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz); + cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf)); + + cmd->cmd_buf_sz = sz; + memcpy(cmd->buf, buf, sz); + return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask) +{ + void *osbuf; + WMI_ALLOW_AGGR_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tx_allow_aggr = tx_tidmask; + cmd->rx_allow_aggr = rx_tidmask; + + return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid) +{ + void *osbuf; + WMI_ADDBA_REQ_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tid = tid; + + return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink) +{ + void *osbuf; + WMI_DELBA_REQ_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tid = tid; + cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */ + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, + bool rxDot11Hdr, bool defragOnHost) +{ + void *osbuf; + WMI_RX_FRAME_FORMAT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0; + cmd->defragOnHost = (defragOnHost==true)? 1:0; + cmd->metaVersion = rxMetaVersion; /* */ + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode) +{ + void *osbuf; + WMI_SET_THIN_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->enable = (bThinMode==true)? 1:0; + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence) +{ + void *osbuf; + WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->precedence = precedence; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk) +{ + void *osbuf; + WMI_SET_PMK_CMD *p; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD)); + + p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(p, sizeof(*p)); + + memcpy(p->pmk, pmk, WMI_PMK_LEN); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd) +{ + void *osbuf; + WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); + + p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf)); + memset(p, 0, sizeof(*p)); + + p->threshold = cmd->threshold; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold) +{ + void *osbuf; + WMI_SET_TX_SGI_PARAM_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY ; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->sgiMask = sgiMask; + cmd->sgiPERThreshold = sgiPERThreshold; + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID, + NO_SYNC_WMIFLAG)); +} + +bss_t * +wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, + u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp) +{ + bss_t *node = NULL; + node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid, + ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp); + + return node; +} + +u16 wmi_ieee2freq (int chan) +{ + u16 freq = 0; + freq = wlan_ieee2freq (chan); + return freq; + +} + +u32 wmi_freq2ieee (u16 freq) +{ + u16 chan = 0; + chan = wlan_freq2ieee (freq); + return chan; +} diff --git a/trunk/drivers/staging/ath6kl/wmi/wmi_host.h b/trunk/drivers/staging/ath6kl/wmi/wmi_host.h new file mode 100644 index 000000000000..53e4f085dfe6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wmi/wmi_host.h @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains local definitios for the wmi host module. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _WMI_HOST_H_ +#define _WMI_HOST_H_ + +#include "roaming.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct wmi_stats { + u32 cmd_len_err; + u32 cmd_id_err; +}; + +#define SSID_IE_LEN_INDEX 13 + +/* Host side link management data structures */ +#define SIGNAL_QUALITY_THRESHOLD_LEVELS 6 +#define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS +#define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS +typedef struct sq_threshold_params_s { + s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS]; + s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS]; + u32 upper_threshold_valid_count; + u32 lower_threshold_valid_count; + u32 polling_interval; + u8 weight; + u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target. + u8 last_rssi_poll_event; //Not sure if it belongs to host or target +} SQ_THRESHOLD_PARAMS; + +/* + * These constants are used with A_WLAN_BAND_SET. + */ +#define A_BAND_24GHZ 0 +#define A_BAND_5GHZ 1 +#define A_NUM_BANDS 2 + +struct wmi_t { + bool wmi_ready; + bool wmi_numQoSStream; + u16 wmi_streamExistsForAC[WMM_NUM_AC]; + u8 wmi_fatPipeExists; + void *wmi_devt; + struct wmi_stats wmi_stats; + struct ieee80211_node_table wmi_scan_table; + u8 wmi_bssid[ATH_MAC_LEN]; + u8 wmi_powerMode; + u8 wmi_phyMode; + u8 wmi_keepaliveInterval; +#ifdef THREAD_X + A_CSECT_T wmi_lock; +#else + A_MUTEX_T wmi_lock; +#endif + HTC_ENDPOINT_ID wmi_endpoint_id; + SQ_THRESHOLD_PARAMS wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX]; + CRYPTO_TYPE wmi_pair_crypto_type; + CRYPTO_TYPE wmi_grp_crypto_type; + bool wmi_is_wmm_enabled; + u8 wmi_ht_allowed[A_NUM_BANDS]; + u8 wmi_traffic_class; +}; + +#ifdef THREAD_X +#define INIT_WMI_LOCK(w) A_CSECT_INIT(&(w)->wmi_lock) +#define LOCK_WMI(w) A_CSECT_ENTER(&(w)->wmi_lock); +#define UNLOCK_WMI(w) A_CSECT_LEAVE(&(w)->wmi_lock); +#define DELETE_WMI_LOCK(w) A_CSECT_DELETE(&(w)->wmi_lock); +#else +#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock); +#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_HOST_H_ */ diff --git a/trunk/include/linux/bcma/bcma_driver_chipcommon.h b/trunk/include/linux/bcma/bcma_driver_chipcommon.h index a7ae33d06f24..6083725dd22e 100644 --- a/trunk/include/linux/bcma/bcma_driver_chipcommon.h +++ b/trunk/include/linux/bcma/bcma_driver_chipcommon.h @@ -283,22 +283,6 @@ #define BCMA_CC_PPL_PCHI_OFF 5 #define BCMA_CC_PPL_PCHI_MASK 0x0000003f -/* BCM4331 ChipControl numbers. */ -#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ -#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ -#define BCMA_CHIPCTL_4331_EXT_LNA BIT(2) /* 0 disable */ -#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15 BIT(3) /* sprom/gpio13-15 mux */ -#define BCMA_CHIPCTL_4331_EXTPA_EN BIT(4) /* 0 ext pa disable, 1 ext pa enabled */ -#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS BIT(5) /* set drive out GPIO_CLK on sprom_cs pin */ -#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS BIT(6) /* use sprom_cs pin as PCIE mdio interface */ -#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 BIT(7) /* aband extpa will be at gpio2/5 and sprom_dout */ -#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN BIT(8) /* override core control on pipe_AuxClkEnable */ -#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ -#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ -#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ -#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ -#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ - /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ @@ -358,8 +342,6 @@ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); extern void bcma_chipco_resume(struct bcma_drv_cc *cc); -void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); - extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 72f3933938c0..54c878960872 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -130,8 +130,6 @@ #define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060 /* A-MSDU 802.11n */ #define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 -/* Mesh Control 802.11s */ -#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 /* U-APSD queue for WMM IEs sent by AP */ #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) @@ -631,14 +629,9 @@ struct ieee80211_rann_ie { u8 rann_ttl; u8 rann_addr[6]; u32 rann_seq; - u32 rann_interval; u32 rann_metric; } __attribute__ ((packed)); -enum ieee80211_rann_flags { - RANN_FLAG_IS_GATE = 1 << 0, -}; - #define WLAN_SA_QUERY_TR_ID_LEN 2 struct ieee80211_mgmt { @@ -743,10 +736,19 @@ struct ieee80211_mgmt { __le16 params; __le16 reason_code; } __attribute__((packed)) delba; - struct { + struct{ u8 action_code; + /* capab_info for open and confirm, + * reason for close + */ + __le16 aux; + /* Followed in plink_confirm by status + * code, AID and supported rates, + * and directly by supported rates in + * plink_open and plink_close + */ u8 variable[0]; - } __attribute__((packed)) self_prot; + } __attribute__((packed)) plink_action; struct{ u8 action_code; u8 variable[0]; @@ -814,11 +816,9 @@ struct ieee80211_bar { } __attribute__((packed)); /* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 -#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 -#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 + #define IEEE80211_HT_MCS_MASK_LEN 10 @@ -1194,6 +1194,11 @@ enum ieee80211_eid { WLAN_EID_MESH_ID = 114, WLAN_EID_LINK_METRIC_REPORT = 115, WLAN_EID_CONGESTION_NOTIFICATION = 116, + /* Note that the Peer Link IE has been replaced with the similar + * Peer Management IE. We will keep the former definition until mesh + * code is changed to comply with latest 802.11s drafts. + */ + WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ WLAN_EID_PEER_MGMT = 117, WLAN_EID_CHAN_SWITCH_PARAM = 118, WLAN_EID_MESH_AWAKE_WINDOW = 119, @@ -1276,6 +1281,9 @@ enum ieee80211_category { WLAN_CATEGORY_MULTIHOP_ACTION = 14, WLAN_CATEGORY_SELF_PROTECTED = 15, WLAN_CATEGORY_WMM = 17, + /* TODO: remove MESH_PATH_SEL after mesh is updated + * to current 802.11s draft */ + WLAN_CATEGORY_MESH_PATH_SEL = 32, WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, WLAN_CATEGORY_VENDOR_SPECIFIC = 127, }; @@ -1301,31 +1309,6 @@ enum ieee80211_ht_actioncode { WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, }; -/* Self Protected Action codes */ -enum ieee80211_self_protected_actioncode { - WLAN_SP_RESERVED = 0, - WLAN_SP_MESH_PEERING_OPEN = 1, - WLAN_SP_MESH_PEERING_CONFIRM = 2, - WLAN_SP_MESH_PEERING_CLOSE = 3, - WLAN_SP_MGK_INFORM = 4, - WLAN_SP_MGK_ACK = 5, -}; - -/* Mesh action codes */ -enum ieee80211_mesh_actioncode { - WLAN_MESH_ACTION_LINK_METRIC_REPORT, - WLAN_MESH_ACTION_HWMP_PATH_SELECTION, - WLAN_MESH_ACTION_GATE_ANNOUNCEMENT, - WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION, - WLAN_MESH_ACTION_MCCA_SETUP_REQUEST, - WLAN_MESH_ACTION_MCCA_SETUP_REPLY, - WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST, - WLAN_MESH_ACTION_MCCA_ADVERTISEMENT, - WLAN_MESH_ACTION_MCCA_TEARDOWN, - WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST, - WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE, -}; - /* Security key length */ enum ieee80211_key_len { WLAN_KEY_LEN_WEP40 = 5, diff --git a/trunk/include/linux/nfc.h b/trunk/include/linux/nfc.h index c525e0b5876b..330a4c5db588 100644 --- a/trunk/include/linux/nfc.h +++ b/trunk/include/linux/nfc.h @@ -123,6 +123,4 @@ struct sockaddr_nfc { #define NFC_SOCKPROTO_RAW 0 #define NFC_SOCKPROTO_MAX 1 -#define NFC_HEADER_SIZE 1 - #endif /*__LINUX_NFC_H */ diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index 8aa7badc1966..8ad70dcac3f9 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -161,13 +161,6 @@ * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * Following attributes are provided for drivers that generate full Beacon - * and Probe Response frames internally: %NL80211_ATTR_SSID, - * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, - * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, - * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, - * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP, - * %NL80211_ATTR_IE_ASSOC_RESP. * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, * parameters are like for %NL80211_CMD_SET_BEACON. * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it @@ -769,8 +762,6 @@ enum nl80211_commands { * that can be added to a scan request * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information * elements that can be added to a scheduled scan request - * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be - * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute. * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -851,20 +842,18 @@ enum nl80211_commands { * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT * event (u16) * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating - * that protected APs should be used. This is also used with NEW_BEACON to - * indicate that the BSS is to use protection. + * that protected APs should be used. * - * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON - * to indicate which unicast key ciphers will be used with the connection + * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to + * indicate which unicast key ciphers will be used with the connection * (an array of u32). - * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to - * indicate which group key cipher will be used with the connection (a - * u32). - * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to - * indicate which WPA version(s) the AP we want to associate with is using + * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate + * which group key cipher will be used with the connection (a u32). + * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate + * which WPA version(s) the AP we want to associate with is using * (a u32 with flags from &enum nl80211_wpa_versions). - * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to - * indicate which key management algorithm(s) to use (an array of u32). + * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate + * which key management algorithm(s) to use (an array of u32). * * @NL80211_ATTR_REQ_IE: (Re)association request information elements as * sent out by the card, for ROAM and successful CONNECT events. @@ -1013,24 +1002,6 @@ enum nl80211_commands { * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan * cycles, in msecs. - - * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more - * sets of attributes to match during scheduled scans. Only BSSs - * that match any of the sets will be reported. These are - * pass-thru filter rules. - * For a match to succeed, the BSS must match all attributes of a - * set. Since not every hardware supports matching all types of - * attributes, there is no guarantee that the reported BSSs are - * fully complying with the match sets and userspace needs to be - * able to ignore them by itself. - * Thus, the implementation is somewhat hardware-dependent, but - * this is only an optimization and the userspace application - * needs to handle all the non-filtered results anyway. - * If the match attributes don't make sense when combined with - * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID - * is included in the probe request, but the match attributes - * will never let it go through), -EINVAL may be returned. - * If ommited, no filtering is done. * * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported * interface combinations. In each nested item, it contains attributes @@ -1048,28 +1019,6 @@ enum nl80211_commands { * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but * without the length restriction (at most %NL80211_MAX_SUPP_RATES). * - * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon - * and Probe Response (when response to wildcard Probe Request); see - * &enum nl80211_hidden_ssid, represented as a u32 - * - * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame. - * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to - * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the - * driver (or firmware) replies to Probe Request frames. - * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association - * Response frames. This is used with %NL80211_CMD_NEW_BEACON and - * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into - * (Re)Association Response frames when the driver (or firmware) replies to - * (Re)Association Request frames. - * - * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration - * of the station, see &enum nl80211_sta_wme_attr. - * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working - * as AP. - * - * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of - * roaming to another AP in the same ESS if the signal lever is low. - * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1275,19 +1224,6 @@ enum nl80211_attrs { NL80211_ATTR_SCAN_SUPP_RATES, - NL80211_ATTR_HIDDEN_SSID, - - NL80211_ATTR_IE_PROBE_RESP, - NL80211_ATTR_IE_ASSOC_RESP, - - NL80211_ATTR_STA_WME, - NL80211_ATTR_SUPPORT_AP_UAPSD, - - NL80211_ATTR_ROAM_SUPPORT, - - NL80211_ATTR_SCHED_SCAN_MATCH, - NL80211_ATTR_MAX_MATCH_SETS, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1746,26 +1682,6 @@ enum nl80211_reg_rule_attr { NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 }; -/** - * enum nl80211_sched_scan_match_attr - scheduled scan match attributes - * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, - * only report BSS with matching SSID. - * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter - * attribute number currently defined - * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use - */ -enum nl80211_sched_scan_match_attr { - __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID, - - NL80211_ATTR_SCHED_SCAN_MATCH_SSID, - - /* keep last */ - __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, - NL80211_SCHED_SCAN_MATCH_ATTR_MAX = - __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1 -}; - /** * enum nl80211_reg_rule_flags - regulatory rule flags * @@ -1917,13 +1833,6 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a * source mesh point for path selection elements. * - * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between - * root announcements are transmitted. - * - * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has - * access to a broader network beyond the MBSS. This is done via Root - * Announcement frames. - * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -1945,8 +1854,6 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, NL80211_MESHCONF_HWMP_ROOTMODE, NL80211_MESHCONF_ELEMENT_TTL, - NL80211_MESHCONF_HWMP_RANN_INTERVAL, - NL80211_MESHCONF_GATE_ANNOUNCEMENTS, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -2523,37 +2430,4 @@ enum nl80211_rekey_data { MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1 }; -/** - * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID - * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in - * Beacon frames) - * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element - * in Beacon frames - * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID - * element in Beacon frames but zero out each byte in the SSID - */ -enum nl80211_hidden_ssid { - NL80211_HIDDEN_SSID_NOT_IN_USE, - NL80211_HIDDEN_SSID_ZERO_LEN, - NL80211_HIDDEN_SSID_ZERO_CONTENTS -}; - -/** - * enum nl80211_sta_wme_attr - station WME attributes - * @__NL80211_STA_WME_INVALID: invalid number for nested attribute - * @NL80211_STA_WME_QUEUES: bitmap of uapsd queues. - * @NL80211_STA_WME_MAX_SP: max service period. - * @__NL80211_STA_WME_AFTER_LAST: internal - * @NL80211_STA_WME_MAX: highest station WME attribute - */ -enum nl80211_sta_wme_attr { - __NL80211_STA_WME_INVALID, - NL80211_STA_WME_UAPSD_QUEUES, - NL80211_STA_WME_MAX_SP, - - /* keep last */ - __NL80211_STA_WME_AFTER_LAST, - NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 -}; - #endif /* __LINUX_NL80211_H */ diff --git a/trunk/include/linux/ssb/ssb.h b/trunk/include/linux/ssb/ssb.h index f10ed7b4a714..8623217f84d0 100644 --- a/trunk/include/linux/ssb/ssb.h +++ b/trunk/include/linux/ssb/ssb.h @@ -25,7 +25,7 @@ struct ssb_sprom { u8 et1phyaddr; /* MII address for enet1 */ u8 et0mdcport; /* MDIO for enet0 */ u8 et1mdcport; /* MDIO for enet1 */ - u16 board_rev; /* Board revision number from SPROM. */ + u8 board_rev; /* Board revision number from SPROM. */ u8 country_code; /* Country Code */ u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */ u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */ diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 95980317d983..ab1244075925 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -333,36 +333,6 @@ struct survey_info { s8 noise; }; -/** - * struct cfg80211_crypto_settings - Crypto settings - * @wpa_versions: indicates which, if any, WPA versions are enabled - * (from enum nl80211_wpa_versions) - * @cipher_group: group key cipher suite (or 0 if unset) - * @n_ciphers_pairwise: number of AP supported unicast ciphers - * @ciphers_pairwise: unicast key cipher suites - * @n_akm_suites: number of AKM suites - * @akm_suites: AKM suites - * @control_port: Whether user space controls IEEE 802.1X port, i.e., - * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is - * required to assume that the port is unauthorized until authorized by - * user space. Otherwise, port is marked authorized by default. - * @control_port_ethertype: the control port protocol that should be - * allowed through even on unauthorized ports - * @control_port_no_encrypt: TRUE to prevent encryption of control port - * protocol frames. - */ -struct cfg80211_crypto_settings { - u32 wpa_versions; - u32 cipher_group; - int n_ciphers_pairwise; - u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES]; - int n_akm_suites; - u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; - bool control_port; - __be16 control_port_ethertype; - bool control_port_no_encrypt; -}; - /** * struct beacon_parameters - beacon parameters * @@ -376,38 +346,11 @@ struct cfg80211_crypto_settings { * @dtim_period: DTIM period or zero if not changed * @head_len: length of @head * @tail_len: length of @tail - * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from - * user space) - * @ssid_len: length of @ssid - * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames - * @crypto: crypto settings - * @privacy: the BSS uses privacy - * @auth_type: Authentication type (algorithm) - * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL - * @beacon_ies_len: length of beacon_ies in octets - * @proberesp_ies: extra information element(s) to add into Probe Response - * frames or %NULL - * @proberesp_ies_len: length of proberesp_ies in octets - * @assocresp_ies: extra information element(s) to add into (Re)Association - * Response frames or %NULL - * @assocresp_ies_len: length of assocresp_ies in octets */ struct beacon_parameters { u8 *head, *tail; int interval, dtim_period; int head_len, tail_len; - const u8 *ssid; - size_t ssid_len; - enum nl80211_hidden_ssid hidden_ssid; - struct cfg80211_crypto_settings crypto; - bool privacy; - enum nl80211_auth_type auth_type; - const u8 *beacon_ies; - size_t beacon_ies_len; - const u8 *proberesp_ies; - size_t proberesp_ies_len; - const u8 *assocresp_ies; - size_t assocresp_ies_len; }; /** @@ -452,8 +395,6 @@ struct station_parameters { u8 plink_action; u8 plink_state; struct ieee80211_ht_cap *ht_capa; - u8 uapsd_queues; - u8 max_sp; }; /** @@ -757,12 +698,6 @@ struct mesh_config { u16 dot11MeshHWMPpreqMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; - u16 dot11MeshHWMPRannInterval; - /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol - * set to true only means that the station will announce others it's a - * mesh gate, but not necessarily using the gate announcement protocol. - * Still keeping the same nomenclature to be in sync with the spec. */ - bool dot11MeshGateAnnouncementProtocol; }; /** @@ -875,15 +810,6 @@ struct cfg80211_scan_request { struct ieee80211_channel *channels[0]; }; -/** - * struct cfg80211_match_set - sets of attributes to match - * - * @ssid: SSID to be matched - */ -struct cfg80211_match_set { - struct cfg80211_ssid ssid; -}; - /** * struct cfg80211_sched_scan_request - scheduled scan request description * @@ -893,11 +819,6 @@ struct cfg80211_match_set { * @interval: interval between each scheduled scan cycle * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets - * @match_sets: sets of parameters to be matched for a scan result - * entry to be considered valid and to be passed to the host - * (others are filtered out). - * If ommited, all results are passed. - * @n_match_sets: number of match sets * @wiphy: the wiphy this was for * @dev: the interface * @channels: channels to scan @@ -909,8 +830,6 @@ struct cfg80211_sched_scan_request { u32 interval; const u8 *ie; size_t ie_len; - struct cfg80211_match_set *match_sets; - int n_match_sets; /* internal */ struct wiphy *wiphy; @@ -986,6 +905,36 @@ struct cfg80211_bss { const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); +/** + * struct cfg80211_crypto_settings - Crypto settings + * @wpa_versions: indicates which, if any, WPA versions are enabled + * (from enum nl80211_wpa_versions) + * @cipher_group: group key cipher suite (or 0 if unset) + * @n_ciphers_pairwise: number of AP supported unicast ciphers + * @ciphers_pairwise: unicast key cipher suites + * @n_akm_suites: number of AKM suites + * @akm_suites: AKM suites + * @control_port: Whether user space controls IEEE 802.1X port, i.e., + * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is + * required to assume that the port is unauthorized until authorized by + * user space. Otherwise, port is marked authorized by default. + * @control_port_ethertype: the control port protocol that should be + * allowed through even on unauthorized ports + * @control_port_no_encrypt: TRUE to prevent encryption of control port + * protocol frames. + */ +struct cfg80211_crypto_settings { + u32 wpa_versions; + u32 cipher_group; + int n_ciphers_pairwise; + u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES]; + int n_akm_suites; + u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; + bool control_port; + __be16 control_port_ethertype; + bool control_port_no_encrypt; +}; + /** * struct cfg80211_auth_request - Authentication request data * @@ -1635,9 +1584,6 @@ struct cfg80211_ops { * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans. - * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the - * firmware. - * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1652,8 +1598,6 @@ enum wiphy_flags { WIPHY_FLAG_MESH_AUTH = BIT(10), WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), - WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13), - WIPHY_FLAG_AP_UAPSD = BIT(14), }; /** @@ -1810,12 +1754,9 @@ struct wiphy_wowlan_support { * by default for perm_addr. In this case, the mask should be set to * all-zeroes. In this case it is assumed that the device can handle * the same number of arbitrary MAC addresses. - * @registered: protects ->resume and ->suspend sysfs callbacks against - * unregister hardware * @debugfsdir: debugfs directory used for this wiphy, will be renamed * automatically on wiphy renames * @dev: (virtual) struct device for this wiphy - * @registered: helps synchronize suspend/resume with wiphy unregister * @wext: wireless extension handlers * @priv: driver private data (sized according to wiphy_new() parameter) * @interface_modes: bitmask of interfaces types valid for this wiphy, @@ -1832,9 +1773,6 @@ struct wiphy_wowlan_support { * any given scan * @max_sched_scan_ssids: maximum number of SSIDs the device can scan * for in any given scheduled scan - * @max_match_sets: maximum number of match sets the device can handle - * when performing a scheduled scan, 0 if filtering is not - * supported. * @max_scan_ie_len: maximum length of user-controlled IEs device can * add to probe request frames transmitted during a scan, must not * include fixed IEs like supported rates @@ -1892,7 +1830,6 @@ struct wiphy { int bss_priv_size; u8 max_scan_ssids; u8 max_sched_scan_ssids; - u8 max_match_sets; u16 max_scan_ie_len; u16 max_sched_scan_ie_len; @@ -2303,69 +2240,6 @@ extern int ieee80211_radiotap_iterator_next( extern const unsigned char rfc1042_header[6]; extern const unsigned char bridge_tunnel_header[6]; -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ie_start; - size_t total_len; - - /* pointers to IEs */ - u8 *ssid; - u8 *supp_rates; - u8 *fh_params; - u8 *ds_params; - u8 *cf_params; - struct ieee80211_tim_ie *tim; - u8 *ibss_params; - u8 *challenge; - u8 *wpa; - u8 *rsn; - u8 *erp_info; - u8 *ext_supp_rates; - u8 *wmm_info; - u8 *wmm_param; - struct ieee80211_ht_cap *ht_cap_elem; - struct ieee80211_ht_info *ht_info_elem; - struct ieee80211_meshconf_ie *mesh_config; - u8 *mesh_id; - u8 *peering; - u8 *preq; - u8 *prep; - u8 *perr; - struct ieee80211_rann_ie *rann; - u8 *ch_switch_elem; - u8 *country_elem; - u8 *pwr_constr_elem; - u8 *quiet_elem; /* first quite element */ - u8 *timeout_int; - - /* length of them, respectively */ - u8 ssid_len; - u8 supp_rates_len; - u8 fh_params_len; - u8 ds_params_len; - u8 cf_params_len; - u8 tim_len; - u8 ibss_params_len; - u8 challenge_len; - u8 wpa_len; - u8 rsn_len; - u8 erp_info_len; - u8 ext_supp_rates_len; - u8 wmm_info_len; - u8 wmm_param_len; - u8 mesh_id_len; - u8 peering_len; - u8 preq_len; - u8 prep_len; - u8 perr_len; - u8 ch_switch_elem_len; - u8 country_elem_len; - u8 pwr_constr_elem_len; - u8 quiet_elem_len; - u8 num_of_quiet_elem; /* can be more the one */ - u8 timeout_int_len; -}; - /** * ieee80211_get_hdrlen_from_skb - get header length from data * diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 643e1291a1e8..2f01d84ca52f 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -164,7 +164,6 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note * that it is only ever disabled for station mode. * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface. - * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -182,7 +181,6 @@ enum ieee80211_bss_change { BSS_CHANGED_ARP_FILTER = 1<<12, BSS_CHANGED_QOS = 1<<13, BSS_CHANGED_IDLE = 1<<14, - BSS_CHANGED_SSID = 1<<15, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -256,9 +254,6 @@ enum ieee80211_rssi_event { * @idle: This interface is idle. There's also a global idle flag in the * hardware config which may be more appropriate depending on what * your driver/device needs to do. - * @ssid: The SSID of the current vif. Only valid in AP-mode. - * @ssid_len: Length of SSID given in @ssid. - * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. */ struct ieee80211_bss_conf { const u8 *bssid; @@ -285,9 +280,6 @@ struct ieee80211_bss_conf { bool arp_filter_enabled; bool qos; bool idle; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - size_t ssid_len; - bool hidden_ssid; }; /** @@ -962,8 +954,6 @@ struct ieee80211_sta { u16 aid; struct ieee80211_sta_ht_cap ht_cap; bool wme; - u8 uapsd_queues; - u8 max_sp; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); @@ -1104,10 +1094,6 @@ enum sta_notify_cmd { * stations based on the PM bit of incoming frames. * Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure * the PS mode of connected stations. - * - * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session - * setup strictly in HW. mac80211 should not attempt to do this in - * software. */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1133,7 +1119,6 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, IEEE80211_HW_AP_LINK_PS = 1<<22, - IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, }; /** @@ -3233,19 +3218,6 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw); void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, const u8 *addr); -/** - * ieee80211_send_bar - send a BlockAckReq frame - * - * can be used to flush pending frames from the peer's aggregation reorder - * buffer. - * - * @vif: &struct ieee80211_vif pointer from the add_interface callback. - * @ra: the peer's destination address - * @tid: the TID of the aggregation session - * @ssn: the new starting sequence number for the receiver - */ -void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); - /* Rate control API */ /** diff --git a/trunk/include/net/nfc.h b/trunk/include/net/nfc.h index 87b51fe15b70..cc0130312f70 100644 --- a/trunk/include/net/nfc.h +++ b/trunk/include/net/nfc.h @@ -82,9 +82,6 @@ struct nfc_dev { struct nfc_genl_data genl_data; u32 supported_protocols; - int tx_headroom; - int tx_tailroom; - struct nfc_ops *ops; }; #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) @@ -92,9 +89,7 @@ struct nfc_dev { extern struct class nfc_class; struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - u32 supported_protocols, - int tx_headroom, - int tx_tailroom); + u32 supported_protocols); /** * nfc_free_device - free nfc device diff --git a/trunk/include/net/regulatory.h b/trunk/include/net/regulatory.h index eb7d3c2d4274..356d6e3dc20a 100644 --- a/trunk/include/net/regulatory.h +++ b/trunk/include/net/regulatory.h @@ -3,19 +3,11 @@ /* * regulatory support structures * - * Copyright 2008-2009 Luis R. Rodriguez + * Copyright 2008-2009 Luis R. Rodriguez * - * Permission to use, copy, modify, and/or 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index d1886b59bec4..f5fdfcbf552a 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -199,19 +199,6 @@ config MAC80211_VERBOSE_MPL_DEBUG Do not select this option. -config MAC80211_VERBOSE_MPATH_DEBUG - bool "Verbose mesh path debugging" - depends on MAC80211_DEBUG_MENU - depends on MAC80211_MESH - ---help--- - Selecting this option causes mac80211 to print out very - verbose mesh path selection debugging messages (when mac80211 - is taking part in a mesh network). - It should not be selected on production systems as those - messages are remotely triggerable. - - Do not select this option. - config MAC80211_VERBOSE_MHWMP_DEBUG bool "Verbose mesh HWMP routing debugging" depends on MAC80211_DEBUG_MENU diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c index e6cab51dceb0..fd1aaf2a4a6c 100644 --- a/trunk/net/mac80211/agg-rx.c +++ b/trunk/net/mac80211/agg-rx.c @@ -167,8 +167,12 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d u16 capab; skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - if (!skb) + + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer " + "for addba resp frame\n", sdata->name); return; + } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); @@ -275,8 +279,14 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* prepare A-MPDU MLME for Rx aggregation */ tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); - if (!tid_agg_rx) + if (!tid_agg_rx) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "allocate rx mlme to tid %d failed\n", + tid); +#endif goto end; + } spin_lock_init(&tid_agg_rx->reorder_lock); @@ -296,6 +306,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, tid_agg_rx->reorder_time = kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "can not allocate reordering buffer " + "to tid %d\n", tid); +#endif kfree(tid_agg_rx->reorder_buf); kfree(tid_agg_rx->reorder_time); kfree(tid_agg_rx); diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index 3cef5a7281cb..b7075f33dc06 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -68,9 +68,11 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - if (!skb) + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer " + "for addba request frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); @@ -104,18 +106,19 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb); } -void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_bar *bar; u16 bar_control = 0; skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); - if (!skb) + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "bar frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); memset(bar, 0, sizeof(*bar)); @@ -125,14 +128,13 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; - bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT); + bar_control |= (u16)(tid << 12); bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } -EXPORT_SYMBOL(ieee80211_send_bar); void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, struct tid_ampdu_tx *tid_tx) @@ -362,8 +364,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, return -EINVAL; if ((tid >= STA_TID_NUM) || - !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || - (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) + !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) return -EINVAL; #ifdef CONFIG_MAC80211_HT_DEBUG @@ -412,6 +413,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, /* prepare A-MPDU MLME for Tx aggregation */ tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); if (!tid_tx) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "allocate tx mlme to tid %d failed\n", + tid); +#endif ret = -ENOMEM; goto err_unlock_sta; } @@ -568,9 +574,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, struct ieee80211_ra_tid *ra_tid; struct sk_buff *skb = dev_alloc_skb(0); - if (unlikely(!skb)) + if (unlikely(!skb)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_WARNING "%s: Not enough memory, " + "dropping start BA session", sdata->name); +#endif return; - + } ra_tid = (struct ieee80211_ra_tid *) &skb->cb; memcpy(&ra_tid->ra, ra, ETH_ALEN); ra_tid->tid = tid; @@ -716,9 +727,14 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, struct ieee80211_ra_tid *ra_tid; struct sk_buff *skb = dev_alloc_skb(0); - if (unlikely(!skb)) + if (unlikely(!skb)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_WARNING "%s: Not enough memory, " + "dropping stop BA session", sdata->name); +#endif return; - + } ra_tid = (struct ieee80211_ra_tid *) &skb->cb; memcpy(&ra_tid->ra, ra, ETH_ALEN); ra_tid->tid = tid; diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index b57ddf941e59..c1fa5775cef2 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -455,20 +455,6 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, return ret; } -static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata, - struct beacon_parameters *params) -{ - struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - - bss_conf->ssid_len = params->ssid_len; - - if (params->ssid_len) - memcpy(bss_conf->ssid, params->ssid, params->ssid_len); - - bss_conf->hidden_ssid = - (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); -} - /* * This handles both adding a beacon and setting new beacon info */ @@ -562,11 +548,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, kfree(old); - ieee80211_config_ap_ssid(sdata, params); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | - BSS_CHANGED_BEACON | - BSS_CHANGED_SSID); + BSS_CHANGED_BEACON); return 0; } @@ -714,9 +697,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, } spin_unlock_irqrestore(&sta->flaglock, flags); - sta->sta.uapsd_queues = params->uapsd_queues; - sta->sta.max_sp = params->max_sp; - /* * cfg80211 validates this (1-2007) and allows setting the AID * only when creating a new station entry @@ -938,7 +918,7 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, if (dst) return mesh_path_del(dst, sdata); - mesh_path_flush_by_iface(sdata); + mesh_path_flush(sdata); return 0; } @@ -1157,22 +1137,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; ieee80211_mesh_root_setup(ifmsh); } - if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) { - /* our current gate announcement implementation rides on root - * announcements, so require this ifmsh to also be a root node - * */ - if (nconf->dot11MeshGateAnnouncementProtocol && - !conf->dot11MeshHWMPRootMode) { - conf->dot11MeshHWMPRootMode = 1; - ieee80211_mesh_root_setup(ifmsh); - } - conf->dot11MeshGateAnnouncementProtocol = - nconf->dot11MeshGateAnnouncementProtocol; - } - if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { - conf->dot11MeshHWMPRannInterval = - nconf->dot11MeshHWMPRannInterval; - } return 0; } diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index c9141168fd43..186e02f7cc32 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -195,12 +195,20 @@ static ssize_t uapsd_queues_write(struct file *file, size_t count, loff_t *ppos) { struct ieee80211_local *local = file->private_data; - u8 val; + unsigned long val; + char buf[10]; + size_t len; int ret; - ret = kstrtou8_from_user(user_buf, count, 0, &val); + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &val); + if (ret) - return ret; + return -EINVAL; if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) return -ERANGE; @@ -297,9 +305,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, char *buf = kzalloc(mxln, GFP_KERNEL); int sf = 0; /* how many written so far */ - if (!buf) - return 0; - sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); @@ -350,8 +355,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); - if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) - sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); kfree(buf); diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index dd0462917518..9ea7c0d0103f 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -340,8 +340,6 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); -IEEE80211_IF_FILE(dropped_frames_congestion, - u.mesh.mshstats.dropped_frames_congestion, DEC); IEEE80211_IF_FILE(dropped_frames_no_route, u.mesh.mshstats.dropped_frames_no_route, DEC); IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); @@ -374,10 +372,6 @@ IEEE80211_IF_FILE(min_discovery_timeout, u.mesh.mshcfg.min_discovery_timeout, DEC); IEEE80211_IF_FILE(dot11MeshHWMPRootMode, u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); -IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, - u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); -IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, - u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); #endif @@ -465,7 +459,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) MESHSTATS_ADD(fwded_frames); MESHSTATS_ADD(dropped_frames_ttl); MESHSTATS_ADD(dropped_frames_no_route); - MESHSTATS_ADD(dropped_frames_congestion); MESHSTATS_ADD(estab_plinks); #undef MESHSTATS_ADD } @@ -492,9 +485,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); MESHPARAMS_ADD(path_refresh_time); MESHPARAMS_ADD(min_discovery_timeout); - MESHPARAMS_ADD(dot11MeshHWMPRootMode); - MESHPARAMS_ADD(dot11MeshHWMPRannInterval); - MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); + #undef MESHPARAMS_ADD } #endif diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index 2b9b52c69569..7cfc286946c0 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -186,8 +186,12 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, u16 params; skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - if (!skb) + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer " + "for delba frame\n", sdata->name); return; + } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 21186e280ceb..286ac5dbeeea 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -261,7 +261,6 @@ struct mesh_stats { __u32 fwded_frames; /* Mesh total forwarded frames */ __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ __u32 dropped_frames_no_route; /* Not transmitted, no route found */ - __u32 dropped_frames_congestion;/* Not forwarded due to congestion */ atomic_t estab_plinks; }; @@ -515,7 +514,6 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; - int num_gates; const u8 *ie; u8 ie_len; enum { @@ -671,7 +669,6 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_AGGREGATION, IEEE80211_QUEUE_STOP_REASON_SUSPEND, IEEE80211_QUEUE_STOP_REASON_SKB_ADD, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE, }; #ifdef CONFIG_MAC80211_LEDS @@ -1024,6 +1021,69 @@ struct ieee80211_ra_tid { u16 tid; }; +/* Parsed Information Elements */ +struct ieee802_11_elems { + u8 *ie_start; + size_t total_len; + + /* pointers to IEs */ + u8 *ssid; + u8 *supp_rates; + u8 *fh_params; + u8 *ds_params; + u8 *cf_params; + struct ieee80211_tim_ie *tim; + u8 *ibss_params; + u8 *challenge; + u8 *wpa; + u8 *rsn; + u8 *erp_info; + u8 *ext_supp_rates; + u8 *wmm_info; + u8 *wmm_param; + struct ieee80211_ht_cap *ht_cap_elem; + struct ieee80211_ht_info *ht_info_elem; + struct ieee80211_meshconf_ie *mesh_config; + u8 *mesh_id; + u8 *peer_link; + u8 *preq; + u8 *prep; + u8 *perr; + struct ieee80211_rann_ie *rann; + u8 *ch_switch_elem; + u8 *country_elem; + u8 *pwr_constr_elem; + u8 *quiet_elem; /* first quite element */ + u8 *timeout_int; + + /* length of them, respectively */ + u8 ssid_len; + u8 supp_rates_len; + u8 fh_params_len; + u8 ds_params_len; + u8 cf_params_len; + u8 tim_len; + u8 ibss_params_len; + u8 challenge_len; + u8 wpa_len; + u8 rsn_len; + u8 erp_info_len; + u8 ext_supp_rates_len; + u8 wmm_info_len; + u8 wmm_param_len; + u8 mesh_id_len; + u8 peer_link_len; + u8 preq_len; + u8 prep_len; + u8 perr_len; + u8 ch_switch_elem_len; + u8 country_elem_len; + u8 pwr_constr_elem_len; + u8 quiet_elem_len; + u8 num_of_quiet_elem; /* can be more the one */ + u8 timeout_int_len; +}; + static inline struct ieee80211_local *hw_to_local( struct ieee80211_hw *hw) { @@ -1188,6 +1248,7 @@ struct ieee80211_tx_status_rtap_hdr { void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_sta_ht_cap *ht_cap); +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index eaa80a3d412b..556e7e6ddf0a 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -1214,9 +1214,6 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) list_del_rcu(&sdata->list); mutex_unlock(&sdata->local->iflist_mtx); - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_path_flush_by_iface(sdata); - synchronize_rcu(); unregister_netdevice(sdata->dev); } @@ -1236,9 +1233,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_path_flush_by_iface(sdata); - unregister_netdevice_queue(sdata->dev, &unreg_list); } mutex_unlock(&local->iflist_mtx); diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index a4225ae69681..29e9980c8e60 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -13,6 +13,10 @@ #include "ieee80211_i.h" #include "mesh.h" +#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) +#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) +#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) + #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 #define MESHCONF_CAPAB_FORWARDING 0x08 @@ -23,17 +27,6 @@ int mesh_allocated; static struct kmem_cache *rm_cache; -#ifdef CONFIG_MAC80211_MESH -bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) -{ - return (mgmt->u.action.u.mesh_action.action_code == - WLAN_MESH_ACTION_HWMP_PATH_SELECTION); -} -#else -bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) -{ return false; } -#endif - void ieee80211s_init(void) { mesh_pathtbl_init(); @@ -200,9 +193,10 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, } p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); - if (!p) + if (!p) { + printk(KERN_DEBUG "o11s: could not allocate RMC entry\n"); return 0; - + } p->seqnum = seqnum; p->exp_time = jiffies + RMC_TIMEOUT; memcpy(p->sa, sa, ETH_ALEN); @@ -210,185 +204,36 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, return 0; } -int -mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 *pos, neighbors; - u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); - - if (skb_tailroom(skb) < 2 + meshconf_len) - return -ENOMEM; - - pos = skb_put(skb, 2 + meshconf_len); - *pos++ = WLAN_EID_MESH_CONFIG; - *pos++ = meshconf_len; - - /* Active path selection protocol ID */ - *pos++ = ifmsh->mesh_pp_id; - /* Active path selection metric ID */ - *pos++ = ifmsh->mesh_pm_id; - /* Congestion control mode identifier */ - *pos++ = ifmsh->mesh_cc_id; - /* Synchronization protocol identifier */ - *pos++ = ifmsh->mesh_sp_id; - /* Authentication Protocol identifier */ - *pos++ = ifmsh->mesh_auth_id; - /* Mesh Formation Info - number of neighbors */ - neighbors = atomic_read(&ifmsh->mshstats.estab_plinks); - /* Number of neighbor mesh STAs or 15 whichever is smaller */ - neighbors = (neighbors > 15) ? 15 : neighbors; - *pos++ = neighbors << 1; - /* Mesh capability */ - ifmsh->accepting_plinks = mesh_plink_availables(sdata); - *pos = MESHCONF_CAPAB_FORWARDING; - *pos++ |= ifmsh->accepting_plinks ? - MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; - *pos++ = 0x00; - - return 0; -} - -int -mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 *pos; - - if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len) - return -ENOMEM; - - pos = skb_put(skb, 2 + ifmsh->mesh_id_len); - *pos++ = WLAN_EID_MESH_ID; - *pos++ = ifmsh->mesh_id_len; - if (ifmsh->mesh_id_len) - memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len); - - return 0; -} - -int -mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 offset, len; - const u8 *data; - - if (!ifmsh->ie || !ifmsh->ie_len) - return 0; - - /* fast-forward to vendor IEs */ - offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0); - - if (offset) { - len = ifmsh->ie_len - offset; - data = ifmsh->ie + offset; - if (skb_tailroom(skb) < len) - return -ENOMEM; - memcpy(skb_put(skb, len), data, len); - } - - return 0; -} - -int -mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 len = 0; - const u8 *data; - - if (!ifmsh->ie || !ifmsh->ie_len) - return 0; - - /* find RSN IE */ - data = ifmsh->ie; - while (data < ifmsh->ie + ifmsh->ie_len) { - if (*data == WLAN_EID_RSN) { - len = data[1] + 2; - break; - } - data++; - } - - if (len) { - if (skb_tailroom(skb) < len) - return -ENOMEM; - memcpy(skb_put(skb, len), data, len); - } - - return 0; -} - -int -mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; - int rate; - u8 i, rates, *pos; + u8 *pos; + int len, i, rate; + u8 neighbors; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - rates = sband->n_bitrates; - if (rates > 8) - rates = 8; - - if (skb_tailroom(skb) < rates + 2) - return -ENOMEM; - - pos = skb_put(skb, rates + 2); + len = sband->n_bitrates; + if (len > 8) + len = 8; + pos = skb_put(skb, len + 2); *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = rates; - for (i = 0; i < rates; i++) { + *pos++ = len; + for (i = 0; i < len; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } - return 0; -} - -int -mesh_add_ext_srates_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - int rate; - u8 i, exrates, *pos; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - exrates = sband->n_bitrates; - if (exrates > 8) - exrates -= 8; - else - exrates = 0; - - if (skb_tailroom(skb) < exrates + 2) - return -ENOMEM; - - if (exrates) { - pos = skb_put(skb, exrates + 2); + if (sband->n_bitrates > len) { + pos = skb_put(skb, sband->n_bitrates - len + 2); *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = exrates; - for (i = 8; i < sband->n_bitrates; i++) { + *pos++ = sband->n_bitrates - len; + for (i = len; i < sband->n_bitrates; i++) { rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } } - return 0; -} -int mesh_add_ds_params_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - u8 *pos; - - if (skb_tailroom(skb) < 3) - return -ENOMEM; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; if (sband->band == IEEE80211_BAND_2GHZ) { pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; @@ -396,9 +241,53 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); } - return 0; + pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); + *pos++ = WLAN_EID_MESH_ID; + *pos++ = sdata->u.mesh.mesh_id_len; + if (sdata->u.mesh.mesh_id_len) + memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); + + pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); + *pos++ = WLAN_EID_MESH_CONFIG; + *pos++ = sizeof(struct ieee80211_meshconf_ie); + + /* Active path selection protocol ID */ + *pos++ = sdata->u.mesh.mesh_pp_id; + + /* Active path selection metric ID */ + *pos++ = sdata->u.mesh.mesh_pm_id; + + /* Congestion control mode identifier */ + *pos++ = sdata->u.mesh.mesh_cc_id; + + /* Synchronization protocol identifier */ + *pos++ = sdata->u.mesh.mesh_sp_id; + + /* Authentication Protocol identifier */ + *pos++ = sdata->u.mesh.mesh_auth_id; + + /* Mesh Formation Info - number of neighbors */ + neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); + /* Number of neighbor mesh STAs or 15 whichever is smaller */ + neighbors = (neighbors > 15) ? 15 : neighbors; + *pos++ = neighbors << 1; + + /* Mesh capability */ + sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); + *pos = MESHCONF_CAPAB_FORWARDING; + *pos++ |= sdata->u.mesh.accepting_plinks ? + MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; + *pos++ = 0x00; + + if (sdata->u.mesh.ie) { + int len = sdata->u.mesh.ie_len; + const u8 *data = sdata->u.mesh.ie; + if (skb_tailroom(skb) > len) + memcpy(skb_put(skb, len), data, len); + } } + static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = @@ -463,7 +352,8 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, memcpy(hdr->addr3, meshsa, ETH_ALEN); return 24; } else { - *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); + *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | + IEEE80211_FCTL_TODS); /* RA TA DA SA */ memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ memcpy(hdr->addr2, meshsa, ETH_ALEN); @@ -535,8 +425,7 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) mesh_path_tx_root_frame(sdata); mod_timer(&ifmsh->mesh_path_root_timer, - round_jiffies(TU_TO_EXP_TIME( - ifmsh->mshcfg.dot11MeshHWMPRannInterval))); + round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); } #ifdef CONFIG_PM @@ -544,7 +433,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - /* use atomic bitops in case all timers fire at the same time */ + /* use atomic bitops in case both timers fire at the same time */ if (del_timer_sync(&ifmsh->housekeeping_timer)) set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); @@ -668,18 +557,11 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_status *rx_status) { switch (mgmt->u.action.category) { - case WLAN_CATEGORY_SELF_PROTECTED: - switch (mgmt->u.action.u.self_prot.action_code) { - case WLAN_SP_MESH_PEERING_OPEN: - case WLAN_SP_MESH_PEERING_CLOSE: - case WLAN_SP_MESH_PEERING_CONFIRM: - mesh_rx_plink_frame(sdata, mgmt, len, rx_status); - break; - } - break; case WLAN_CATEGORY_MESH_ACTION: - if (mesh_action_is_path_sel(mgmt)) - mesh_rx_path_sel_frame(sdata, mgmt, len); + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + break; + case WLAN_CATEGORY_MESH_PATH_SEL: + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } @@ -751,7 +633,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ifmsh->accepting_plinks = true; ifmsh->preq_id = 0; ifmsh->sn = 0; - ifmsh->num_gates = 0; atomic_set(&ifmsh->mpaths, 0); mesh_rmc_init(sdata); ifmsh->last_preq = jiffies; diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 7118e8e8855c..249e733362e7 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -80,10 +80,7 @@ enum mesh_deferred_task_flags { * retry * @discovery_retries: number of discovery retries * @flags: mesh path flags, as specified on &enum mesh_path_flags - * @state_lock: mesh path state lock used to protect changes to the - * mpath itself. No need to take this lock when adding or removing - * an mpath to a hash bucket on a path table. - * @is_gate: the destination station of this path is a mesh gate + * @state_lock: mesh path state lock * * * The combination of dst and sdata is unique in the mesh path table. Since the @@ -107,7 +104,6 @@ struct mesh_path { u8 discovery_retries; enum mesh_path_flags flags; spinlock_t state_lock; - bool is_gate; }; /** @@ -124,9 +120,6 @@ struct mesh_path { * buckets * @mean_chain_len: maximum average length for the hash buckets' list, if it is * reached, the table will grow - * @known_gates: list of known mesh gates and their mpaths by the station. The - * gate's mpath may or may not be resolved and active. - * * rcu_head: RCU head to free the table */ struct mesh_table { @@ -140,8 +133,6 @@ struct mesh_table { int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); int size_order; int mean_chain_len; - struct hlist_head *known_gates; - spinlock_t gates_lock; struct rcu_head rcu_head; }; @@ -175,8 +166,6 @@ struct mesh_rmc { u32 idx_mask; }; -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) -#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ @@ -188,6 +177,14 @@ struct mesh_rmc { /* Maximum number of paths per interface */ #define MESH_MAX_MPATHS 1024 +/* Pending ANA approval */ +#define MESH_PATH_SEL_ACTION 0 + +/* PERR reason codes */ +#define PEER_RCODE_UNSPECIFIED 11 +#define PERR_RCODE_NO_ROUTE 12 +#define PERR_RCODE_DEST_UNREACH 13 + /* Public interfaces */ /* Various */ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, @@ -202,20 +199,6 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); -int mesh_add_meshconf_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_meshid_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_rsn_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_vendor_ies(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_srates_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_ext_srates_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); -int mesh_add_ds_params_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); @@ -240,13 +223,10 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); void mesh_path_expire(struct ieee80211_sub_if_data *sdata); +void mesh_path_flush(struct ieee80211_sub_if_data *sdata); void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); - -int mesh_path_add_gate(struct mesh_path *mpath); -int mesh_path_send_to_gates(struct mesh_path *mpath); -int mesh_gate_num(struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, @@ -276,14 +256,12 @@ void mesh_pathtbl_unregister(void); int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); -void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); void mesh_path_discard_frame(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); void mesh_path_restart(struct ieee80211_sub_if_data *sdata); void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); -bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); extern int mesh_paths_generation; #ifdef CONFIG_MAC80211_MESH diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index 6df7913d7ca4..3d8e55ae6ab6 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -8,12 +8,10 @@ */ #include -#include "wme.h" #include "mesh.h" #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG -#define mhwmp_dbg(fmt, args...) \ - printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) +#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) #else #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) #endif @@ -70,12 +68,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) #define PREP_IE_TTL(x) PREQ_IE_TTL(x) -#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) -#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x)) +#define PREP_IE_ORIG_ADDR(x) (x + 3) +#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) -#define PREP_IE_TARGET_ADDR(x) (x + 3) -#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0) +#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) +#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) #define PERR_IE_TTL(x) (*(x)) #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) @@ -134,25 +132,24 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID == SA */ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; - mgmt->u.action.u.mesh_action.action_code = - WLAN_MESH_ACTION_HWMP_PATH_SELECTION; + mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; + mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; switch (action) { case MPATH_PREQ: - mhwmp_dbg("sending PREQ to %pM", target); + mhwmp_dbg("sending PREQ to %pM\n", target); ie_len = 37; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PREQ; break; case MPATH_PREP: - mhwmp_dbg("sending PREP to %pM", target); + mhwmp_dbg("sending PREP to %pM\n", target); ie_len = 31; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PREP; break; case MPATH_RANN: - mhwmp_dbg("sending RANN from %pM", orig_addr); + mhwmp_dbg("sending RANN from %pM\n", orig_addr); ie_len = sizeof(struct ieee80211_rann_ie); pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_RANN; @@ -166,63 +163,35 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, *pos++ = flags; *pos++ = hop_count; *pos++ = ttl; - if (action == MPATH_PREP) { - memcpy(pos, target, ETH_ALEN); - pos += ETH_ALEN; - memcpy(pos, &target_sn, 4); - pos += 4; - } else { - if (action == MPATH_PREQ) { - memcpy(pos, &preq_id, 4); - pos += 4; - } - memcpy(pos, orig_addr, ETH_ALEN); - pos += ETH_ALEN; - memcpy(pos, &orig_sn, 4); + if (action == MPATH_PREQ) { + memcpy(pos, &preq_id, 4); pos += 4; } - memcpy(pos, &lifetime, 4); /* interval for RANN */ + memcpy(pos, orig_addr, ETH_ALEN); + pos += ETH_ALEN; + memcpy(pos, &orig_sn, 4); pos += 4; + if (action != MPATH_RANN) { + memcpy(pos, &lifetime, 4); + pos += 4; + } memcpy(pos, &metric, 4); pos += 4; if (action == MPATH_PREQ) { - *pos++ = 1; /* destination count */ + /* destination count */ + *pos++ = 1; *pos++ = target_flags; + } + if (action != MPATH_RANN) { memcpy(pos, target, ETH_ALEN); pos += ETH_ALEN; memcpy(pos, &target_sn, 4); - pos += 4; - } else if (action == MPATH_PREP) { - memcpy(pos, orig_addr, ETH_ALEN); - pos += ETH_ALEN; - memcpy(pos, &orig_sn, 4); - pos += 4; } ieee80211_tx_skb(sdata, skb); return 0; } - -/* Headroom is not adjusted. Caller should ensure that skb has sufficient - * headroom in case the frame is encrypted. */ -static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - skb_set_mac_header(skb, 0); - skb_set_network_header(skb, 0); - skb_set_transport_header(skb, 0); - - /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ - skb_set_queue_mapping(skb, IEEE80211_AC_VO); - skb->priority = 7; - - info->control.vif = &sdata->vif; - ieee80211_set_qos_hdr(sdata, skb); -} - /** * mesh_send_path error - Sends a PERR mesh management frame * @@ -230,10 +199,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, * @target_sn: SN of the broken destination * @target_rcode: reason code for this PERR * @ra: node this frame is addressed to - * - * Note: This function may be called with driver locks taken that the driver - * also acquires in the TX path. To avoid a deadlock we don't transmit the - * frame directly but add it to the pending queue instead. */ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, const u8 *ra, @@ -247,7 +212,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, if (!skb) return -1; - skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); + skb_reserve(skb, local->hw.extra_tx_headroom); /* 25 is the size of the common mgmt part (24) plus the size of the * common action part (1) */ @@ -259,11 +224,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, memcpy(mgmt->da, ra, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - /* BSSID == SA */ - memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; - mgmt->u.action.u.mesh_action.action_code = - WLAN_MESH_ACTION_HWMP_PATH_SELECTION; + /* BSSID is left zeroed, wildcard value */ + mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; + mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; ie_len = 15; pos = skb_put(skb, 2 + ie_len); *pos++ = WLAN_EID_PERR; @@ -288,9 +251,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, pos += 4; memcpy(pos, &target_rcode, 2); - /* see note in function header */ - prepare_frame_for_deferred_tx(sdata, skb); - ieee80211_add_pending_skb(local, skb); + ieee80211_tx_skb(sdata, skb); return 0; } @@ -522,10 +483,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, orig_sn = PREQ_IE_ORIG_SN(preq_elem); target_flags = PREQ_IE_TARGET_F(preq_elem); - mhwmp_dbg("received PREQ from %pM", orig_addr); + mhwmp_dbg("received PREQ from %pM\n", orig_addr); if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { - mhwmp_dbg("PREQ is for us"); + mhwmp_dbg("PREQ is for us\n"); forward = false; reply = true; metric = 0; @@ -561,7 +522,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, lifetime = PREQ_IE_LIFETIME(preq_elem); ttl = ifmsh->mshcfg.element_ttl; if (ttl != 0) { - mhwmp_dbg("replying to the PREQ"); + mhwmp_dbg("replying to the PREQ\n"); mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, cpu_to_le32(target_sn), 0, orig_addr, cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, @@ -581,7 +542,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ifmsh->mshstats.dropped_frames_ttl++; return; } - mhwmp_dbg("forwarding the PREQ from %pM", orig_addr); + mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); --ttl; flags = PREQ_IE_FLAGS(preq_elem); preq_id = PREQ_IE_PREQ_ID(preq_elem); @@ -616,7 +577,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, u8 next_hop[ETH_ALEN]; u32 target_sn, orig_sn, lifetime; - mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); + mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); /* Note that we divert from the draft nomenclature and denominate * destination to what the draft refers to as origininator. So in this @@ -722,8 +683,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, u8 ttl, flags, hopcount; u8 *orig_addr; u32 orig_sn, metric; - u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; - bool root_is_gate; ttl = rann->rann_ttl; if (ttl <= 1) { @@ -732,19 +691,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, } ttl--; flags = rann->rann_flags; - root_is_gate = !!(flags & RANN_FLAG_IS_GATE); orig_addr = rann->rann_addr; orig_sn = rann->rann_seq; hopcount = rann->rann_hopcount; hopcount++; metric = rann->rann_metric; - - /* Ignore our own RANNs */ - if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) - return; - - mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr, - root_is_gate); + mhwmp_dbg("received RANN from %pM\n", orig_addr); rcu_read_lock(); mpath = mesh_path_lookup(orig_addr, sdata); @@ -756,28 +708,18 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, sdata->u.mesh.mshstats.dropped_frames_no_route++; return; } + mesh_queue_preq(mpath, + PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - - if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) || - time_after(jiffies, mpath->exp_time - 1*HZ)) && - !(mpath->flags & MESH_PATH_FIXED)) { - mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name, - orig_addr); - mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); - } - if (mpath->sn < orig_sn) { mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, cpu_to_le32(orig_sn), 0, NULL, 0, broadcast_addr, - hopcount, ttl, cpu_to_le32(interval), + hopcount, ttl, 0, cpu_to_le32(metric + mpath->metric), 0, sdata); mpath->sn = orig_sn; } - if (root_is_gate) - mesh_path_add_gate(mpath); - rcu_read_unlock(); } @@ -845,7 +787,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); if (!preq_node) { - mhwmp_dbg("could not allocate PREQ node"); + mhwmp_dbg("could not allocate PREQ node\n"); return; } @@ -854,7 +796,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); kfree(preq_node); if (printk_ratelimit()) - mhwmp_dbg("PREQ node queue full"); + mhwmp_dbg("PREQ node queue full\n"); return; } @@ -1039,46 +981,35 @@ void mesh_path_timer(unsigned long data) { struct mesh_path *mpath = (void *) data; struct ieee80211_sub_if_data *sdata = mpath->sdata; - int ret; if (sdata->local->quiescing) return; spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_RESOLVED || - (!(mpath->flags & MESH_PATH_RESOLVING))) { + (!(mpath->flags & MESH_PATH_RESOLVING))) mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); - spin_unlock_bh(&mpath->state_lock); - } else if (mpath->discovery_retries < max_preq_retries(sdata)) { + else if (mpath->discovery_retries < max_preq_retries(sdata)) { ++mpath->discovery_retries; mpath->discovery_timeout *= 2; - spin_unlock_bh(&mpath->state_lock); mesh_queue_preq(mpath, 0); } else { mpath->flags = 0; mpath->exp_time = jiffies; - spin_unlock_bh(&mpath->state_lock); - if (!mpath->is_gate && mesh_gate_num(sdata) > 0) { - ret = mesh_path_send_to_gates(mpath); - if (ret) - mhwmp_dbg("no gate was reachable"); - } else - mesh_path_flush_pending(mpath); + mesh_path_flush_pending(mpath); } + + spin_unlock_bh(&mpath->state_lock); } void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; - u8 flags; - flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol) - ? RANN_FLAG_IS_GATE : 0; - mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr, + mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, cpu_to_le32(++ifmsh->sn), 0, NULL, 0, broadcast_addr, 0, sdata->u.mesh.mshcfg.element_ttl, - cpu_to_le32(interval), 0, 0, sdata); + 0, 0, 0, sdata); } diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index 332b5ff1e885..068ee6518254 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -14,16 +14,9 @@ #include #include #include -#include "wme.h" #include "ieee80211_i.h" #include "mesh.h" -#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG -#define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) -#else -#define mpath_dbg(fmt, args...) do { (void)(0); } while (0) -#endif - /* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */ #define INIT_PATHS_SIZE_ORDER 2 @@ -49,10 +42,8 @@ static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ int mesh_paths_generation; /* This lock will have the grow table function as writer and add / delete nodes - * as readers. RCU provides sufficient protection only when reading the table - * (i.e. doing lookups). Adding or adding or removing nodes requires we take - * the read lock or we risk operating on an old table. The write lock is only - * needed when modifying the number of buckets a table. + * as readers. When reading the table (i.e. doing lookups) we are well protected + * by RCU */ static DEFINE_RWLOCK(pathtbl_resize_lock); @@ -69,8 +60,6 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void) lockdep_is_held(&pathtbl_resize_lock)); } -static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath); - /* * CAREFUL -- "tbl" must not be an expression, * in particular not an rcu_dereference(), since @@ -114,7 +103,6 @@ static struct mesh_table *mesh_table_alloc(int size_order) sizeof(newtbl->hash_rnd)); for (i = 0; i <= newtbl->hash_mask; i++) spin_lock_init(&newtbl->hashwlock[i]); - spin_lock_init(&newtbl->gates_lock); return newtbl; } @@ -130,7 +118,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) { struct hlist_head *mesh_hash; struct hlist_node *p, *q; - struct mpath_node *gate; int i; mesh_hash = tbl->hash_buckets; @@ -142,17 +129,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) } spin_unlock_bh(&tbl->hashwlock[i]); } - if (free_leafs) { - spin_lock_bh(&tbl->gates_lock); - hlist_for_each_entry_safe(gate, p, q, - tbl->known_gates, list) { - hlist_del(&gate->list); - kfree(gate); - } - kfree(tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); - } - __mesh_table_free(tbl); } @@ -170,7 +146,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl, newtbl->free_node = oldtbl->free_node; newtbl->mean_chain_len = oldtbl->mean_chain_len; newtbl->copy_node = oldtbl->copy_node; - newtbl->known_gates = oldtbl->known_gates; atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); oldhash = oldtbl->hash_buckets; @@ -213,7 +188,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) struct ieee80211_hdr *hdr; struct sk_buff_head tmpq; unsigned long flags; - struct ieee80211_sub_if_data *sdata = mpath->sdata; rcu_assign_pointer(mpath->next_hop, sta); @@ -224,8 +198,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { hdr = (struct ieee80211_hdr *) skb->data; memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); - skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb)); - ieee80211_set_qos_hdr(sdata, skb); __skb_queue_tail(&tmpq, skb); } @@ -233,128 +205,62 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); } -static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, - struct mesh_path *gate_mpath) -{ - struct ieee80211_hdr *hdr; - struct ieee80211s_hdr *mshdr; - int mesh_hdrlen, hdrlen; - char *next_hop; - - hdr = (struct ieee80211_hdr *) skb->data; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - - if (!(mshdr->flags & MESH_FLAGS_AE)) { - /* size of the fixed part of the mesh header */ - mesh_hdrlen = 6; - - /* make room for the two extended addresses */ - skb_push(skb, 2 * ETH_ALEN); - memmove(skb->data, hdr, hdrlen + mesh_hdrlen); - - hdr = (struct ieee80211_hdr *) skb->data; - - /* we preserve the previous mesh header and only add - * the new addreses */ - mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - mshdr->flags = MESH_FLAGS_AE_A5_A6; - memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN); - memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN); - } - - /* update next hop */ - hdr = (struct ieee80211_hdr *) skb->data; - rcu_read_lock(); - next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; - memcpy(hdr->addr1, next_hop, ETH_ALEN); - rcu_read_unlock(); - memcpy(hdr->addr3, dst_addr, ETH_ALEN); -} /** + * mesh_path_lookup - look up a path in the mesh path table + * @dst: hardware address (ETH_ALEN length) of destination + * @sdata: local subif * - * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another - * - * This function is used to transfer or copy frames from an unresolved mpath to - * a gate mpath. The function also adds the Address Extension field and - * updates the next hop. - * - * If a frame already has an Address Extension field, only the next hop and - * destination addresses are updated. - * - * The gate mpath must be an active mpath with a valid mpath->next_hop. + * Returns: pointer to the mesh path structure, or NULL if not found * - * @mpath: An active mpath the frames will be sent to (i.e. the gate) - * @from_mpath: The failed mpath - * @copy: When true, copy all the frames to the new mpath queue. When false, - * move them. + * Locking: must be called within a read rcu section. */ -static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, - struct mesh_path *from_mpath, - bool copy) +struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { - struct sk_buff *skb, *cp_skb = NULL; - struct sk_buff_head gateq, failq; - unsigned long flags; - int num_skbs; - - BUG_ON(gate_mpath == from_mpath); - BUG_ON(!gate_mpath->next_hop); - - __skb_queue_head_init(&gateq); - __skb_queue_head_init(&failq); - - spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); - skb_queue_splice_init(&from_mpath->frame_queue, &failq); - spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); + struct mesh_path *mpath; + struct hlist_node *n; + struct hlist_head *bucket; + struct mesh_table *tbl; + struct mpath_node *node; - num_skbs = skb_queue_len(&failq); + tbl = rcu_dereference(mesh_paths); - while (num_skbs--) { - skb = __skb_dequeue(&failq); - if (copy) { - cp_skb = skb_copy(skb, GFP_ATOMIC); - if (cp_skb) - __skb_queue_tail(&failq, cp_skb); + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; + hlist_for_each_entry_rcu(node, n, bucket, list) { + mpath = node->mpath; + if (mpath->sdata == sdata && + memcmp(dst, mpath->dst, ETH_ALEN) == 0) { + if (MPATH_EXPIRED(mpath)) { + spin_lock_bh(&mpath->state_lock); + if (MPATH_EXPIRED(mpath)) + mpath->flags &= ~MESH_PATH_ACTIVE; + spin_unlock_bh(&mpath->state_lock); + } + return mpath; } - - prepare_for_gate(skb, gate_mpath->dst, gate_mpath); - __skb_queue_tail(&gateq, skb); } - - spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); - skb_queue_splice(&gateq, &gate_mpath->frame_queue); - mpath_dbg("Mpath queue for gate %pM has %d frames\n", - gate_mpath->dst, - skb_queue_len(&gate_mpath->frame_queue)); - spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); - - if (!copy) - return; - - spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); - skb_queue_splice(&failq, &from_mpath->frame_queue); - spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); + return NULL; } - -static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, - struct ieee80211_sub_if_data *sdata) +struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct hlist_node *n; struct hlist_head *bucket; + struct mesh_table *tbl; struct mpath_node *node; + tbl = rcu_dereference(mpp_paths); + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; hlist_for_each_entry_rcu(node, n, bucket, list) { mpath = node->mpath; if (mpath->sdata == sdata && - memcmp(dst, mpath->dst, ETH_ALEN) == 0) { + memcmp(dst, mpath->dst, ETH_ALEN) == 0) { if (MPATH_EXPIRED(mpath)) { spin_lock_bh(&mpath->state_lock); - mpath->flags &= ~MESH_PATH_ACTIVE; + if (MPATH_EXPIRED(mpath)) + mpath->flags &= ~MESH_PATH_ACTIVE; spin_unlock_bh(&mpath->state_lock); } return mpath; @@ -363,25 +269,6 @@ static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, return NULL; } -/** - * mesh_path_lookup - look up a path in the mesh path table - * @dst: hardware address (ETH_ALEN length) of destination - * @sdata: local subif - * - * Returns: pointer to the mesh path structure, or NULL if not found - * - * Locking: must be called within a read rcu section. - */ -struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) -{ - return path_lookup(rcu_dereference(mesh_paths), dst, sdata); -} - -struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) -{ - return path_lookup(rcu_dereference(mpp_paths), dst, sdata); -} - /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index @@ -406,7 +293,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data if (j++ == idx) { if (MPATH_EXPIRED(node->mpath)) { spin_lock_bh(&node->mpath->state_lock); - node->mpath->flags &= ~MESH_PATH_ACTIVE; + if (MPATH_EXPIRED(node->mpath)) + node->mpath->flags &= ~MESH_PATH_ACTIVE; spin_unlock_bh(&node->mpath->state_lock); } return node->mpath; @@ -416,109 +304,6 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data return NULL; } -static void mesh_gate_node_reclaim(struct rcu_head *rp) -{ - struct mpath_node *node = container_of(rp, struct mpath_node, rcu); - kfree(node); -} - -/** - * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates - * @mesh_tbl: table which contains known_gates list - * @mpath: mpath to known mesh gate - * - * Returns: 0 on success - * - */ -static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath) -{ - struct mpath_node *gate, *new_gate; - struct hlist_node *n; - int err; - - rcu_read_lock(); - tbl = rcu_dereference(tbl); - - hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) - if (gate->mpath == mpath) { - err = -EEXIST; - goto err_rcu; - } - - new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (!new_gate) { - err = -ENOMEM; - goto err_rcu; - } - - mpath->is_gate = true; - mpath->sdata->u.mesh.num_gates++; - new_gate->mpath = mpath; - spin_lock_bh(&tbl->gates_lock); - hlist_add_head_rcu(&new_gate->list, tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); - rcu_read_unlock(); - mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n", - mpath->sdata->name, mpath->dst, - mpath->sdata->u.mesh.num_gates); - return 0; -err_rcu: - rcu_read_unlock(); - return err; -} - -/** - * mesh_gate_del - remove a mesh gate from the list of known gates - * @tbl: table which holds our list of known gates - * @mpath: gate mpath - * - * Returns: 0 on success - * - * Locking: must be called inside rcu_read_lock() section - */ -static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) -{ - struct mpath_node *gate; - struct hlist_node *p, *q; - - tbl = rcu_dereference(tbl); - - hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) - if (gate->mpath == mpath) { - spin_lock_bh(&tbl->gates_lock); - hlist_del_rcu(&gate->list); - call_rcu(&gate->rcu, mesh_gate_node_reclaim); - spin_unlock_bh(&tbl->gates_lock); - mpath->sdata->u.mesh.num_gates--; - mpath->is_gate = false; - mpath_dbg("Mesh path (%s): Deleted gate: %pM. " - "%d known gates\n", mpath->sdata->name, - mpath->dst, mpath->sdata->u.mesh.num_gates); - break; - } - - return 0; -} - -/** - * - * mesh_path_add_gate - add the given mpath to a mesh gate to our path table - * @mpath: gate path to add to table - */ -int mesh_path_add_gate(struct mesh_path *mpath) -{ - return mesh_gate_add(mesh_paths, mpath); -} - -/** - * mesh_gate_num - number of gates known to this interface - * @sdata: subif data - */ -int mesh_gate_num(struct ieee80211_sub_if_data *sdata) -{ - return sdata->u.mesh.num_gates; -} - /** * mesh_path_add - allocate and add a new path to the mesh path table * @addr: destination address of the path (ETH_ALEN length) @@ -696,7 +481,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; - init_timer(&new_mpath->timer); new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); @@ -755,53 +539,28 @@ void mesh_plink_broken(struct sta_info *sta) struct hlist_node *p; struct ieee80211_sub_if_data *sdata = sta->sdata; int i; - __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE); rcu_read_lock(); tbl = rcu_dereference(mesh_paths); for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; + spin_lock_bh(&mpath->state_lock); if (rcu_dereference(mpath->next_hop) == sta && mpath->flags & MESH_PATH_ACTIVE && !(mpath->flags & MESH_PATH_FIXED)) { - spin_lock_bh(&mpath->state_lock); mpath->flags &= ~MESH_PATH_ACTIVE; ++mpath->sn; spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, mpath->dst, cpu_to_le32(mpath->sn), - reason, bcast, sdata); - } + cpu_to_le16(PERR_RCODE_DEST_UNREACH), + bcast, sdata); + } else + spin_unlock_bh(&mpath->state_lock); } rcu_read_unlock(); } -static void mesh_path_node_reclaim(struct rcu_head *rp) -{ - struct mpath_node *node = container_of(rp, struct mpath_node, rcu); - struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - - del_timer_sync(&node->mpath->timer); - atomic_dec(&sdata->u.mesh.mpaths); - kfree(node->mpath); - kfree(node); -} - -/* needs to be called with the corresponding hashwlock taken */ -static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) -{ - struct mesh_path *mpath; - mpath = node->mpath; - spin_lock(&mpath->state_lock); - mpath->flags |= MESH_PATH_RESOLVING; - if (mpath->is_gate) - mesh_gate_del(tbl, mpath); - hlist_del_rcu(&node->list); - call_rcu(&node->rcu, mesh_path_node_reclaim); - spin_unlock(&mpath->state_lock); - atomic_dec(&tbl->entries); -} - /** * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches * @@ -822,59 +581,42 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) int i; rcu_read_lock(); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); + tbl = rcu_dereference(mesh_paths); for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; - if (rcu_dereference(mpath->next_hop) == sta) { - spin_lock_bh(&tbl->hashwlock[i]); - __mesh_path_del(tbl, node); - spin_unlock_bh(&tbl->hashwlock[i]); - } + if (rcu_dereference(mpath->next_hop) == sta) + mesh_path_del(mpath->dst, mpath->sdata); } - read_unlock_bh(&pathtbl_resize_lock); rcu_read_unlock(); } -static void table_flush_by_iface(struct mesh_table *tbl, - struct ieee80211_sub_if_data *sdata) +void mesh_path_flush(struct ieee80211_sub_if_data *sdata) { + struct mesh_table *tbl; struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; int i; - WARN_ON(!rcu_read_lock_held()); + rcu_read_lock(); + tbl = rcu_dereference(mesh_paths); for_each_mesh_entry(tbl, p, node, i) { mpath = node->mpath; - if (mpath->sdata != sdata) - continue; - spin_lock_bh(&tbl->hashwlock[i]); - __mesh_path_del(tbl, node); - spin_unlock_bh(&tbl->hashwlock[i]); + if (mpath->sdata == sdata) + mesh_path_del(mpath->dst, mpath->sdata); } + rcu_read_unlock(); } -/** - * mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface - * - * This function deletes both mesh paths as well as mesh portal paths. - * - * @sdata - interface data to match - * - */ -void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) +static void mesh_path_node_reclaim(struct rcu_head *rp) { - struct mesh_table *tbl; + struct mpath_node *node = container_of(rp, struct mpath_node, rcu); + struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - rcu_read_lock(); - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); - table_flush_by_iface(tbl, sdata); - tbl = resize_dereference_mpp_paths(); - table_flush_by_iface(tbl, sdata); - read_unlock_bh(&pathtbl_resize_lock); - rcu_read_unlock(); + del_timer_sync(&node->mpath->timer); + atomic_dec(&sdata->u.mesh.mpaths); + kfree(node->mpath); + kfree(node); } /** @@ -905,7 +647,12 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) mpath = node->mpath; if (mpath->sdata == sdata && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { - __mesh_path_del(tbl, node); + spin_lock(&mpath->state_lock); + mpath->flags |= MESH_PATH_RESOLVING; + hlist_del_rcu(&node->list); + call_rcu(&node->rcu, mesh_path_node_reclaim); + atomic_dec(&tbl->entries); + spin_unlock(&mpath->state_lock); goto enddel; } } @@ -933,58 +680,6 @@ void mesh_path_tx_pending(struct mesh_path *mpath) &mpath->frame_queue); } -/** - * mesh_path_send_to_gates - sends pending frames to all known mesh gates - * - * @mpath: mesh path whose queue will be emptied - * - * If there is only one gate, the frames are transferred from the failed mpath - * queue to that gate's queue. If there are more than one gates, the frames - * are copied from each gate to the next. After frames are copied, the - * mpath queues are emptied onto the transmission queue. - */ -int mesh_path_send_to_gates(struct mesh_path *mpath) -{ - struct ieee80211_sub_if_data *sdata = mpath->sdata; - struct hlist_node *n; - struct mesh_table *tbl; - struct mesh_path *from_mpath = mpath; - struct mpath_node *gate = NULL; - bool copy = false; - struct hlist_head *known_gates; - - rcu_read_lock(); - tbl = rcu_dereference(mesh_paths); - known_gates = tbl->known_gates; - rcu_read_unlock(); - - if (!known_gates) - return -EHOSTUNREACH; - - hlist_for_each_entry_rcu(gate, n, known_gates, list) { - if (gate->mpath->sdata != sdata) - continue; - - if (gate->mpath->flags & MESH_PATH_ACTIVE) { - mpath_dbg("Forwarding to %pM\n", gate->mpath->dst); - mesh_path_move_to_queue(gate->mpath, from_mpath, copy); - from_mpath = gate->mpath; - copy = true; - } else { - mpath_dbg("Not forwarding %p\n", gate->mpath); - mpath_dbg("flags %x\n", gate->mpath->flags); - } - } - - hlist_for_each_entry_rcu(gate, n, known_gates, list) - if (gate->mpath->sdata == sdata) { - mpath_dbg("Sending to %pM\n", gate->mpath->dst); - mesh_path_tx_pending(gate->mpath); - } - - return (from_mpath == mpath) ? -EHOSTUNREACH : 0; -} - /** * mesh_path_discard_frame - discard a frame whose path could not be resolved * @@ -1004,23 +699,18 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct mesh_path *mpath; u32 sn = 0; - __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { u8 *ra, *da; da = hdr->addr3; ra = hdr->addr1; - rcu_read_lock(); mpath = mesh_path_lookup(da, sdata); - if (mpath) { - spin_lock_bh(&mpath->state_lock); + if (mpath) sn = ++mpath->sn; - spin_unlock_bh(&mpath->state_lock); - } - rcu_read_unlock(); mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, - cpu_to_le32(sn), reason, ra, sdata); + cpu_to_le32(sn), + cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); } kfree_skb(skb); @@ -1038,7 +728,8 @@ void mesh_path_flush_pending(struct mesh_path *mpath) { struct sk_buff *skb; - while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) + while ((skb = skb_dequeue(&mpath->frame_queue)) && + (mpath->flags & MESH_PATH_ACTIVE)) mesh_path_discard_frame(skb, mpath->sdata); } @@ -1099,7 +790,6 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) int mesh_pathtbl_init(void) { struct mesh_table *tbl_path, *tbl_mpp; - int ret; tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); if (!tbl_path) @@ -1107,40 +797,21 @@ int mesh_pathtbl_init(void) tbl_path->free_node = &mesh_path_node_free; tbl_path->copy_node = &mesh_path_node_copy; tbl_path->mean_chain_len = MEAN_CHAIN_LEN; - tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); - if (!tbl_path->known_gates) { - ret = -ENOMEM; - goto free_path; - } - INIT_HLIST_HEAD(tbl_path->known_gates); - tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); if (!tbl_mpp) { - ret = -ENOMEM; - goto free_path; + mesh_table_free(tbl_path, true); + return -ENOMEM; } tbl_mpp->free_node = &mesh_path_node_free; tbl_mpp->copy_node = &mesh_path_node_copy; tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; - tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); - if (!tbl_mpp->known_gates) { - ret = -ENOMEM; - goto free_mpp; - } - INIT_HLIST_HEAD(tbl_mpp->known_gates); /* Need no locking since this is during init */ RCU_INIT_POINTER(mesh_paths, tbl_path); RCU_INIT_POINTER(mpp_paths, tbl_mpp); return 0; - -free_mpp: - mesh_table_free(tbl_mpp, true); -free_path: - mesh_table_free(tbl_path, true); - return ret; } void mesh_path_expire(struct ieee80211_sub_if_data *sdata) @@ -1157,10 +828,14 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) if (node->mpath->sdata != sdata) continue; mpath = node->mpath; + spin_lock_bh(&mpath->state_lock); if ((!(mpath->flags & MESH_PATH_RESOLVING)) && (!(mpath->flags & MESH_PATH_FIXED)) && - time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) + time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { + spin_unlock_bh(&mpath->state_lock); mesh_path_del(mpath->dst, mpath->sdata); + } else + spin_unlock_bh(&mpath->state_lock); } rcu_read_unlock(); } diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 4396906175ae..f4adc0917888 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -19,18 +19,35 @@ #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) #endif -#define PLINK_GET_LLID(p) (p + 2) -#define PLINK_GET_PLID(p) (p + 4) +#define PLINK_GET_LLID(p) (p + 4) +#define PLINK_GET_PLID(p) (p + 6) #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ jiffies + HZ * t / 1000)) +/* Peer link cancel reasons, all subject to ANA approval */ +#define MESH_LINK_CANCELLED 2 +#define MESH_MAX_NEIGHBORS 3 +#define MESH_CAPABILITY_POLICY_VIOLATION 4 +#define MESH_CLOSE_RCVD 5 +#define MESH_MAX_RETRIES 6 +#define MESH_CONFIRM_TIMEOUT 7 +#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8 +#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 +#define MESH_SECURITY_FAILED_VERIFICATION 10 + #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) +enum plink_frame_type { + PLINK_OPEN = 1, + PLINK_CONFIRM, + PLINK_CLOSE +}; + enum plink_event { PLINK_UNDEFINED, OPN_ACPT, @@ -88,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; - sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME; + sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; rate_control_rate_init(sta); @@ -140,16 +157,16 @@ void mesh_plink_deactivate(struct sta_info *sta) } static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, - enum ieee80211_self_protected_actioncode action, - u8 *da, __le16 llid, __le16 plid, __le16 reason) { + enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, + __le16 reason) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + sdata->u.mesh.ie_len); struct ieee80211_mgmt *mgmt; bool include_plid = false; - int ie_len = 4; - u16 peering_proto = 0; + static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; u8 *pos; + int ie_len; if (!skb) return -1; @@ -158,75 +175,63 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, * common action part (1) */ mgmt = (struct ieee80211_mgmt *) - skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); - memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot)); + skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); + memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED; - mgmt->u.action.u.self_prot.action_code = action; - - if (action != WLAN_SP_MESH_PEERING_CLOSE) { - /* capability info */ - pos = skb_put(skb, 2); - memset(pos, 0, 2); - if (action == WLAN_SP_MESH_PEERING_CONFIRM) { - /* AID */ - pos = skb_put(skb, 2); + mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; + mgmt->u.action.u.plink_action.action_code = action; + + if (action == PLINK_CLOSE) + mgmt->u.action.u.plink_action.aux = reason; + else { + mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); + if (action == PLINK_CONFIRM) { + pos = skb_put(skb, 4); + /* two-byte status code followed by two-byte AID */ + memset(pos, 0, 2); memcpy(pos + 2, &plid, 2); } - if (mesh_add_srates_ie(skb, sdata) || - mesh_add_ext_srates_ie(skb, sdata) || - mesh_add_rsn_ie(skb, sdata) || - mesh_add_meshid_ie(skb, sdata) || - mesh_add_meshconf_ie(skb, sdata)) - return -1; - } else { /* WLAN_SP_MESH_PEERING_CLOSE */ - if (mesh_add_meshid_ie(skb, sdata)) - return -1; + mesh_mgmt_ies_add(skb, sdata); } - /* Add Mesh Peering Management element */ + /* Add Peer Link Management element */ switch (action) { - case WLAN_SP_MESH_PEERING_OPEN: + case PLINK_OPEN: + ie_len = 6; break; - case WLAN_SP_MESH_PEERING_CONFIRM: - ie_len += 2; + case PLINK_CONFIRM: + ie_len = 8; include_plid = true; break; - case WLAN_SP_MESH_PEERING_CLOSE: - if (plid) { - ie_len += 2; + case PLINK_CLOSE: + default: + if (!plid) + ie_len = 8; + else { + ie_len = 10; include_plid = true; } - ie_len += 2; /* reason code */ break; - default: - return -EINVAL; } - if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) - return -ENOMEM; - pos = skb_put(skb, 2 + ie_len); - *pos++ = WLAN_EID_PEER_MGMT; + *pos++ = WLAN_EID_PEER_LINK; *pos++ = ie_len; - memcpy(pos, &peering_proto, 2); - pos += 2; + memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto)); + pos += 4; memcpy(pos, &llid, 2); - pos += 2; if (include_plid) { - memcpy(pos, &plid, 2); pos += 2; + memcpy(pos, &plid, 2); } - if (action == WLAN_SP_MESH_PEERING_CLOSE) { - memcpy(pos, &reason, 2); + if (action == PLINK_CLOSE) { pos += 2; + memcpy(pos, &reason, 2); } - if (mesh_add_vendor_ies(skb, sdata)) - return -1; ieee80211_tx_skb(sdata, skb); return 0; @@ -317,21 +322,21 @@ static void mesh_plink_timer(unsigned long data) ++sta->plink_retries; mod_plink_timer(sta, sta->plink_timeout); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, - sta->sta.addr, llid, 0, 0); + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, + 0, 0); break; } - reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES); + reason = cpu_to_le16(MESH_MAX_RETRIES); /* fall through on else */ case NL80211_PLINK_CNF_RCVD: /* confirm timer */ if (!reason) - reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); + reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); sta->plink_state = NL80211_PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, + reason); break; case NL80211_PLINK_HOLDING: /* holding timer */ @@ -391,7 +396,7 @@ int mesh_plink_open(struct sta_info *sta) mpl_dbg("Mesh plink: starting establishment with %pM\n", sta->sta.addr); - return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, + return mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, 0, 0); } @@ -417,7 +422,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m struct ieee802_11_elems elems; struct sta_info *sta; enum plink_event event; - enum ieee80211_self_protected_actioncode ftype; + enum plink_frame_type ftype; size_t baselen; bool deactivated, matches_local = true; u8 ie_len; @@ -444,15 +449,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - baseaddr = mgmt->u.action.u.self_prot.variable; - baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; - if (mgmt->u.action.u.self_prot.action_code == - WLAN_SP_MESH_PEERING_CONFIRM) { + baseaddr = mgmt->u.action.u.plink_action.variable; + baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; + if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { baseaddr += 4; baselen += 4; } ieee802_11_parse_elems(baseaddr, len - baselen, &elems); - if (!elems.peering) { + if (!elems.peer_link) { mpl_dbg("Mesh plink: missing necessary peer link ie\n"); return; } @@ -462,34 +466,31 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - ftype = mgmt->u.action.u.self_prot.action_code; - ie_len = elems.peering_len; - if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || - (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || - (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 - && ie_len != 8)) { + ftype = mgmt->u.action.u.plink_action.action_code; + ie_len = elems.peer_link_len; + if ((ftype == PLINK_OPEN && ie_len != 6) || + (ftype == PLINK_CONFIRM && ie_len != 8) || + (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) { mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } - if (ftype != WLAN_SP_MESH_PEERING_CLOSE && - (!elems.mesh_id || !elems.mesh_config)) { + if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) { mpl_dbg("Mesh plink: missing necessary ie\n"); return; } /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ - memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); - if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || - (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) - memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); + memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); + if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10)) + memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); - if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) { + if (!sta && ftype != PLINK_OPEN) { mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); rcu_read_unlock(); return; @@ -508,30 +509,30 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; - if (ftype != WLAN_SP_MESH_PEERING_CLOSE && - (!mesh_matches_local(&elems, sdata))) { + if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { matches_local = false; switch (ftype) { - case WLAN_SP_MESH_PEERING_OPEN: + case PLINK_OPEN: event = OPN_RJCT; break; - case WLAN_SP_MESH_PEERING_CONFIRM: + case PLINK_CONFIRM: event = CNF_RJCT; break; - default: + case PLINK_CLOSE: + /* avoid warning */ break; } } if (!sta && !matches_local) { rcu_read_unlock(); - reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); llid = 0; - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - mgmt->sa, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, + plid, reason); return; } else if (!sta) { - /* ftype == WLAN_SP_MESH_PEERING_OPEN */ + /* ftype == PLINK_OPEN */ u32 rates; rcu_read_unlock(); @@ -556,21 +557,21 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } else if (matches_local) { spin_lock_bh(&sta->lock); switch (ftype) { - case WLAN_SP_MESH_PEERING_OPEN: + case PLINK_OPEN: if (!mesh_plink_free_count(sdata) || (sta->plid && sta->plid != plid)) event = OPN_IGNR; else event = OPN_ACPT; break; - case WLAN_SP_MESH_PEERING_CONFIRM: + case PLINK_CONFIRM: if (!mesh_plink_free_count(sdata) || (sta->llid != llid || sta->plid != plid)) event = CNF_IGNR; else event = CNF_ACPT; break; - case WLAN_SP_MESH_PEERING_CLOSE: + case PLINK_CLOSE: if (sta->plink_state == NL80211_PLINK_ESTAB) /* Do not check for llid or plid. This does not * follow the standard but since multiple plinks @@ -619,12 +620,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->llid = llid; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_OPEN, - sta->sta.addr, llid, 0, 0); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CONFIRM, - sta->sta.addr, llid, plid, 0); + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, + 0, 0); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, + llid, plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -636,10 +635,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); + reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -648,9 +647,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, + plid, reason); break; case OPN_ACPT: /* retry timer is left untouched */ @@ -658,9 +656,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CONFIRM, - sta->sta.addr, llid, plid, 0); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, + plid, 0); break; case CNF_ACPT: sta->plink_state = NL80211_PLINK_CNF_RCVD; @@ -680,10 +677,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); + reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -692,15 +689,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, + plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CONFIRM, - sta->sta.addr, llid, plid, 0); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, + plid, 0); break; case CNF_ACPT: del_timer(&sta->plink_timer); @@ -721,10 +717,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m switch (event) { case OPN_RJCT: case CNF_RJCT: - reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); case CLS_ACPT: if (!reason) - reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); + reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, @@ -733,9 +729,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, + plid, reason); break; case OPN_ACPT: del_timer(&sta->plink_timer); @@ -745,9 +740,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); mpl_dbg("Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CONFIRM, - sta->sta.addr, llid, plid, 0); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, + plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -758,7 +752,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case NL80211_PLINK_ESTAB: switch (event) { case CLS_ACPT: - reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); + reason = cpu_to_le16(MESH_CLOSE_RCVD); sta->reason = reason; deactivated = __mesh_plink_deactivate(sta); sta->plink_state = NL80211_PLINK_HOLDING; @@ -767,15 +761,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); if (deactivated) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, + plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, - WLAN_SP_MESH_PEERING_CONFIRM, - sta->sta.addr, llid, plid, 0); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, + plid, 0); break; default: spin_unlock_bh(&sta->lock); @@ -797,8 +790,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; reason = sta->reason; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, llid, plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, + llid, plid, reason); break; default: spin_unlock_bh(&sta->lock); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 2f92ae2f9706..d6470c7fd6ce 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -271,9 +271,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for " + "deauth/disassoc frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); @@ -352,9 +354,11 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, return; skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr " + "nullfunc frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); @@ -390,9 +394,6 @@ static void ieee80211_chswitch_work(struct work_struct *work) /* call "hw_config" only if doing sw channel switch */ ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); - } else { - /* update the device channel directly */ - sdata->local->hw.conf.channel = sdata->local->oper_channel; } /* XXX: shouldn't really modify cfg80211-owned data! */ @@ -1481,14 +1482,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, ifmgd->aid = aid; - mutex_lock(&sdata->local->sta_mtx); - /* - * station info was already allocated and inserted before - * the association and should be available to us - */ - sta = sta_info_get_rx(sdata, cbss->bssid); - if (WARN_ON(!sta)) { - mutex_unlock(&sdata->local->sta_mtx); + sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); + if (!sta) { + printk(KERN_DEBUG "%s: failed to alloc STA entry for" + " the AP\n", sdata->name); return false; } @@ -1559,8 +1556,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, if (elems.wmm_param) set_sta_flags(sta, WLAN_STA_WME); - /* sta_info_reinsert will also unlock the mutex lock */ - err = sta_info_reinsert(sta); + err = sta_info_insert(sta); sta = NULL; if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" @@ -1921,24 +1917,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - /* - * Whenever the AP announces the HT mode change that can be - * 40MHz intolerant or etc., it would be safer to stop tx - * queues before doing hw config to avoid buffer overflow. - */ - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); - - /* flush out all packets */ - synchronize_net(); - - drv_flush(local, false); - changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, bssid, ap_ht_cap_flags); - - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); } /* Note: country IE parsing is done for us by cfg80211 */ @@ -2449,29 +2429,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, return 0; } -/* create and insert a dummy station entry */ -static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, - u8 *bssid) { - struct sta_info *sta; - int err; - - sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); - if (!sta) - return -ENOMEM; - - sta->dummy = true; - - err = sta_info_insert(sta); - sta = NULL; - if (err) { - printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" - " the AP (error %d)\n", sdata->name, err); - return err; - } - - return 0; -} - static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, struct sk_buff *skb) { @@ -2479,11 +2436,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt; struct ieee80211_rx_status *rx_status; struct ieee802_11_elems elems; - struct cfg80211_bss *cbss = wk->assoc.bss; u16 status; if (!skb) { - sta_info_destroy_addr(wk->sdata, cbss->bssid); cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); goto destroy; } @@ -2513,16 +2468,12 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { mutex_unlock(&wk->sdata->u.mgd.mtx); /* oops -- internal error -- send timeout for now */ - sta_info_destroy_addr(wk->sdata, cbss->bssid); cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); return WORK_DONE_DESTROY; } mutex_unlock(&wk->sdata->u.mgd.mtx); - } else { - /* assoc failed - destroy the dummy station entry */ - sta_info_destroy_addr(wk->sdata, cbss->bssid); } cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); @@ -2541,7 +2492,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_work *wk; const u8 *ssid; - int i, err; + int i; mutex_lock(&ifmgd->mtx); if (ifmgd->associated) { @@ -2566,16 +2517,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (!wk) return -ENOMEM; - /* - * create a dummy station info entry in order - * to start accepting incoming EAPOL packets from the station - */ - err = ieee80211_pre_assoc(sdata, req->bss->bssid); - if (err) { - kfree(wk); - return err; - } - ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.c b/trunk/net/mac80211/rc80211_minstrel_ht.c index e19249b0f971..21588386a302 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht.c @@ -452,8 +452,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { minstrel_ht_update_stats(mp, mi); - if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) - minstrel_aggr_check(mp, sta, skb); + minstrel_aggr_check(mp, sta, skb); } } diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index db46601e50bf..fe2c2a717793 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -476,6 +476,7 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); char *dev_addr = rx->sdata->vif.addr; if (ieee80211_is_data(hdr->frame_control)) { @@ -523,6 +524,14 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) } +#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) + + if (ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && + mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata)) + return RX_DROP_MONITOR; +#undef msh_h_get + return RX_CONTINUE; } @@ -841,21 +850,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ieee80211_is_pspoll(hdr->frame_control)) && rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_WDS && - (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { - if (rx->sta && rx->sta->dummy && - ieee80211_is_data_present(hdr->frame_control)) { - u16 ethertype; - u8 *payload; - - payload = rx->skb->data + - ieee80211_hdrlen(hdr->frame_control); - ethertype = (payload[6] << 8) | payload[7]; - if (cpu_to_be16(ethertype) == - rx->sdata->control_port_protocol) - return RX_CONTINUE; - } + (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) return RX_DROP_MONITOR; - } return RX_CONTINUE; } @@ -1831,12 +1827,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - /* frame is in RMC, don't forward */ - if (ieee80211_is_data(hdr->frame_control) && - is_multicast_ether_addr(hdr->addr1) && - mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) - return RX_DROP_MONITOR; - if (!ieee80211_is_data(hdr->frame_control)) return RX_CONTINUE; @@ -1844,12 +1834,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) /* illegal frame */ return RX_DROP_MONITOR; - if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) { - IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, - dropped_frames_congestion); - return RX_DROP_MONITOR; - } - if (mesh_hdr->flags & MESH_FLAGS_AE) { struct mesh_path *mppath; char *proxied_addr; @@ -1905,13 +1889,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) memset(info, 0, sizeof(*info)); info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; info->control.vif = &rx->sdata->vif; - if (is_multicast_ether_addr(fwd_hdr->addr1)) { + skb_set_queue_mapping(skb, + ieee80211_select_queue(rx->sdata, fwd_skb)); + ieee80211_set_qos_hdr(local, skb); + if (is_multicast_ether_addr(fwd_hdr->addr1)) IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, fwded_mcast); - skb_set_queue_mapping(fwd_skb, - ieee80211_select_queue(sdata, fwd_skb)); - ieee80211_set_qos_hdr(sdata, fwd_skb); - } else { + else { int err; /* * Save TA to addr1 to send TA a path error if a @@ -2236,29 +2220,12 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto handled; } break; - case WLAN_CATEGORY_SELF_PROTECTED: - switch (mgmt->u.action.u.self_prot.action_code) { - case WLAN_SP_MESH_PEERING_OPEN: - case WLAN_SP_MESH_PEERING_CLOSE: - case WLAN_SP_MESH_PEERING_CONFIRM: - if (!ieee80211_vif_is_mesh(&sdata->vif)) - goto invalid; - if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) - /* userspace handles this frame */ - break; - goto queue; - case WLAN_SP_MGK_INFORM: - case WLAN_SP_MGK_ACK: - if (!ieee80211_vif_is_mesh(&sdata->vif)) - goto invalid; - break; - } - break; case WLAN_CATEGORY_MESH_ACTION: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; - if (mesh_action_is_path_sel(mgmt) && - (!mesh_path_sel_is_hwmp(sdata))) + goto queue; + case WLAN_CATEGORY_MESH_PATH_SEL: + if (!mesh_path_sel_is_hwmp(sdata)) break; goto queue; } @@ -2572,12 +2539,12 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) CALL_RXH(ieee80211_rx_h_ps_poll) CALL_RXH(ieee80211_rx_h_michael_mic_verify) /* must be after MMIC verify so header is counted in MPDU mic */ + CALL_RXH(ieee80211_rx_h_remove_qos_control) + CALL_RXH(ieee80211_rx_h_amsdu) #ifdef CONFIG_MAC80211_MESH if (ieee80211_vif_is_mesh(&rx->sdata->vif)) CALL_RXH(ieee80211_rx_h_mesh_fwding); #endif - CALL_RXH(ieee80211_rx_h_remove_qos_control) - CALL_RXH(ieee80211_rx_h_amsdu) CALL_RXH(ieee80211_rx_h_data) CALL_RXH(ieee80211_rx_h_ctrl); CALL_RXH(ieee80211_rx_h_mgmt_check) @@ -2719,9 +2686,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && - !ieee80211_is_beacon(hdr->frame_control) && - !(ieee80211_is_action(hdr->frame_control) && - sdata->vif.p2p)) + !ieee80211_is_beacon(hdr->frame_control)) return 0; status->rx_flags &= ~IEEE80211_RX_RA_MATCH; } @@ -2826,7 +2791,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc)) { prev_sta = NULL; - for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { + for_each_sta_info(local, hdr->addr2, sta, tmp) { if (!prev_sta) { prev_sta = sta; continue; @@ -2870,7 +2835,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } - rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; ieee80211_prepare_and_rx_handle(&rx, skb, false); @@ -2878,7 +2843,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (prev) { - rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) diff --git a/trunk/net/mac80211/spectmgmt.c b/trunk/net/mac80211/spectmgmt.c index 578eea3fc04d..7733f66ee2c4 100644 --- a/trunk/net/mac80211/spectmgmt.c +++ b/trunk/net/mac80211/spectmgmt.c @@ -32,8 +32,12 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + sizeof(struct ieee80211_msrment_ie)); - if (!skb) + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "measurement report frame\n", sdata->name); return; + } skb_reserve(skb, local->hw.extra_tx_headroom); msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 42c196e86115..5eaa1673a8f5 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -96,27 +96,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], - lockdep_is_held(&local->sta_lock) || - lockdep_is_held(&local->sta_mtx)); - while (sta) { - if (sta->sdata == sdata && !sta->dummy && - memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) - break; - sta = rcu_dereference_check(sta->hnext, - lockdep_is_held(&local->sta_lock) || - lockdep_is_held(&local->sta_mtx)); - } - return sta; -} - -/* get a station info entry even if it is a dummy station*/ -struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], lockdep_is_held(&local->sta_lock) || lockdep_is_held(&local->sta_mtx)); @@ -141,32 +120,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], - lockdep_is_held(&local->sta_lock) || - lockdep_is_held(&local->sta_mtx)); - while (sta) { - if ((sta->sdata == sdata || - (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && - !sta->dummy && - memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) - break; - sta = rcu_dereference_check(sta->hnext, - lockdep_is_held(&local->sta_lock) || - lockdep_is_held(&local->sta_mtx)); - } - return sta; -} - -/* - * Get sta info either from the specified interface - * or from one of its vlans (including dummy stations) - */ -struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], lockdep_is_held(&local->sta_lock) || lockdep_is_held(&local->sta_mtx)); @@ -327,8 +280,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return sta; } -static int sta_info_finish_insert(struct sta_info *sta, - bool async, bool dummy_reinsert) +static int sta_info_finish_insert(struct sta_info *sta, bool async) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -338,58 +290,51 @@ static int sta_info_finish_insert(struct sta_info *sta, lockdep_assert_held(&local->sta_mtx); - if (!sta->dummy || dummy_reinsert) { - /* notify driver */ - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - err = drv_sta_add(local, sdata, &sta->sta); - if (err) { - if (!async) - return err; - printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " - "driver (%d) - keeping it anyway.\n", - sdata->name, sta->sta.addr, err); - } else { - sta->uploaded = true; + /* notify driver */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + err = drv_sta_add(local, sdata, &sta->sta); + if (err) { + if (!async) + return err; + printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" + " - keeping it anyway.\n", + sdata->name, sta->sta.addr, err); + } else { + sta->uploaded = true; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - if (async) - wiphy_debug(local->hw.wiphy, - "Finished adding IBSS STA %pM\n", - sta->sta.addr); + if (async) + wiphy_debug(local->hw.wiphy, + "Finished adding IBSS STA %pM\n", + sta->sta.addr); #endif - } - - sdata = sta->sdata; } - if (!dummy_reinsert) { - if (!async) { - local->num_sta++; - local->sta_generation++; - smp_mb(); + sdata = sta->sdata; - /* make the station visible */ - spin_lock_irqsave(&local->sta_lock, flags); - sta_info_hash_add(local, sta); - spin_unlock_irqrestore(&local->sta_lock, flags); - } + if (!async) { + local->num_sta++; + local->sta_generation++; + smp_mb(); - list_add(&sta->list, &local->sta_list); - } else { - sta->dummy = false; + /* make the station visible */ + spin_lock_irqsave(&local->sta_lock, flags); + sta_info_hash_add(local, sta); + spin_unlock_irqrestore(&local->sta_lock, flags); } - if (!sta->dummy) { - ieee80211_sta_debugfs_add(sta); - rate_control_add_sta_debugfs(sta); + list_add(&sta->list, &local->sta_list); + + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); + + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); - memset(&sinfo, 0, sizeof(sinfo)); - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); - } return 0; } @@ -406,7 +351,7 @@ static void sta_info_finish_pending(struct ieee80211_local *local) list_del(&sta->list); spin_unlock_irqrestore(&local->sta_lock, flags); - sta_info_finish_insert(sta, true, false); + sta_info_finish_insert(sta, true); spin_lock_irqsave(&local->sta_lock, flags); } @@ -423,117 +368,106 @@ static void sta_info_finish_work(struct work_struct *work) mutex_unlock(&local->sta_mtx); } -static int sta_info_insert_check(struct sta_info *sta) +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) { + struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; + unsigned long flags; + int err = 0; /* * Can't be a WARN_ON because it can be triggered through a race: * something inserts a STA (on one CPU) without holding the RTNL * and another CPU turns off the net device. */ - if (unlikely(!ieee80211_sdata_running(sdata))) - return -ENETDOWN; + if (unlikely(!ieee80211_sdata_running(sdata))) { + err = -ENETDOWN; + rcu_read_lock(); + goto out_free; + } if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || - is_multicast_ether_addr(sta->sta.addr))) - return -EINVAL; - - return 0; -} - -static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) -{ - struct ieee80211_local *local = sta->local; - struct ieee80211_sub_if_data *sdata = sta->sdata; - unsigned long flags; - - spin_lock_irqsave(&local->sta_lock, flags); - /* check if STA exists already */ - if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { - spin_unlock_irqrestore(&local->sta_lock, flags); + is_multicast_ether_addr(sta->sta.addr))) { + err = -EINVAL; rcu_read_lock(); - return -EEXIST; + goto out_free; } - local->num_sta++; - local->sta_generation++; - smp_mb(); - sta_info_hash_add(local, sta); + /* + * In ad-hoc mode, we sometimes need to insert stations + * from tasklet context from the RX path. To avoid races, + * always do so in that case -- see the comment below. + */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + spin_lock_irqsave(&local->sta_lock, flags); + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); + err = -EEXIST; + goto out_free; + } - list_add_tail(&sta->list, &local->sta_pending_list); + local->num_sta++; + local->sta_generation++; + smp_mb(); + sta_info_hash_add(local, sta); - rcu_read_lock(); - spin_unlock_irqrestore(&local->sta_lock, flags); + list_add_tail(&sta->list, &local->sta_pending_list); + + rcu_read_lock(); + spin_unlock_irqrestore(&local->sta_lock, flags); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", - sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", + sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - ieee80211_queue_work(&local->hw, &local->sta_finish_work); - - return 0; -} - -/* - * should be called with sta_mtx locked - * this function replaces the mutex lock - * with a RCU lock - */ -static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) -{ - struct ieee80211_local *local = sta->local; - struct ieee80211_sub_if_data *sdata = sta->sdata; - unsigned long flags; - struct sta_info *exist_sta; - bool dummy_reinsert = false; - int err = 0; + ieee80211_queue_work(&local->hw, &local->sta_finish_work); - lockdep_assert_held(&local->sta_mtx); + return 0; + } /* * On first glance, this will look racy, because the code - * in this function, which inserts a station with sleeping, + * below this point, which inserts a station with sleeping, * unlocks the sta_lock between checking existence in the * hash table and inserting into it. * * However, it is not racy against itself because it keeps - * the mutex locked. + * the mutex locked. It still seems to race against the + * above code that atomically inserts the station... That, + * however, is not true because the above code can only + * be invoked for IBSS interfaces, and the below code will + * not be -- and the two do not race against each other as + * the hash table also keys off the interface. */ + might_sleep(); + + mutex_lock(&local->sta_mtx); + spin_lock_irqsave(&local->sta_lock, flags); - /* - * check if STA exists already. - * only accept a scenario of a second call to sta_info_insert_non_ibss - * with a dummy station entry that was inserted earlier - * in that case - assume that the dummy station flag should - * be removed. - */ - exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); - if (exist_sta) { - if (exist_sta == sta && sta->dummy) { - dummy_reinsert = true; - } else { - spin_unlock_irqrestore(&local->sta_lock, flags); - mutex_unlock(&local->sta_mtx); - rcu_read_lock(); - return -EEXIST; - } + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); + rcu_read_lock(); + err = -EEXIST; + goto out_free; } spin_unlock_irqrestore(&local->sta_lock, flags); - err = sta_info_finish_insert(sta, false, dummy_reinsert); + err = sta_info_finish_insert(sta, false); if (err) { mutex_unlock(&local->sta_mtx); rcu_read_lock(); - return err; + goto out_free; } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", - sta->dummy ? "dummy " : "", sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ /* move reference to rcu-protected */ @@ -543,51 +477,6 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_accept_plinks_update(sdata); - return 0; -} - -int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) -{ - struct ieee80211_local *local = sta->local; - struct ieee80211_sub_if_data *sdata = sta->sdata; - int err = 0; - - err = sta_info_insert_check(sta); - if (err) { - rcu_read_lock(); - goto out_free; - } - - /* - * In ad-hoc mode, we sometimes need to insert stations - * from tasklet context from the RX path. To avoid races, - * always do so in that case -- see the comment below. - */ - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - err = sta_info_insert_ibss(sta); - if (err) - goto out_free; - - return 0; - } - - /* - * It might seem that the function called below is in race against - * the function call above that atomically inserts the station... That, - * however, is not true because the above code can only - * be invoked for IBSS interfaces, and the below code will - * not be -- and the two do not race against each other as - * the hash table also keys off the interface. - */ - - might_sleep(); - - mutex_lock(&local->sta_mtx); - - err = sta_info_insert_non_ibss(sta); - if (err) - goto out_free; - return 0; out_free: BUG_ON(!err); @@ -604,25 +493,6 @@ int sta_info_insert(struct sta_info *sta) return err; } -/* Caller must hold sta->local->sta_mtx */ -int sta_info_reinsert(struct sta_info *sta) -{ - struct ieee80211_local *local = sta->local; - int err = 0; - - err = sta_info_insert_check(sta); - if (err) { - mutex_unlock(&local->sta_mtx); - return err; - } - - might_sleep(); - - err = sta_info_insert_non_ibss(sta); - rcu_read_unlock(); - return err; -} - static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) { /* @@ -691,13 +561,14 @@ void sta_info_clear_tim_bit(struct sta_info *sta) spin_unlock_irqrestore(&sta->local->sta_lock, flags); } -static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) +static int sta_info_buffer_expired(struct sta_info *sta, + struct sk_buff *skb) { struct ieee80211_tx_info *info; int timeout; if (!skb) - return false; + return 0; info = IEEE80211_SKB_CB(skb); @@ -717,6 +588,9 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, unsigned long flags; struct sk_buff *skb; + if (skb_queue_empty(&sta->ps_tx_buf)) + return false; + for (;;) { spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); skb = skb_peek(&sta->ps_tx_buf); @@ -741,7 +615,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, sta_info_clear_tim_bit(sta); } - return !skb_queue_empty(&sta->ps_tx_buf); + return true; } static int __must_check __sta_info_destroy(struct sta_info *sta) @@ -859,7 +733,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get_rx(sdata, addr); + sta = sta_info_get(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); @@ -873,7 +747,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get_bss_rx(sdata, addr); + sta = sta_info_get_bss(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 56a3d38a2cd1..28beb78e601e 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -86,8 +86,6 @@ enum ieee80211_sta_info_flags { * @stop_initiator: initiator of a session stop * @tx_stop: TX DelBA frame when stopping * @buf_size: reorder buffer size at receiver - * @failed_bar_ssn: ssn of the last failed BAR tx attempt - * @bar_pending: BAR needs to be re-sent * * This structure's lifetime is managed by RCU, assignments to * the array holding it must hold the aggregation mutex. @@ -108,9 +106,6 @@ struct tid_ampdu_tx { u8 stop_initiator; bool tx_stop; u8 buf_size; - - u16 failed_bar_ssn; - bool bar_pending; }; /** @@ -243,12 +238,10 @@ struct sta_ampdu_mlme { * @plink_timer: peer link watch timer * @plink_timer_was_running: used by suspend/resume to restore timers * @debugfs: debug filesystem info + * @sta: station information we share with the driver * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver * @lost_packets: number of consecutive lost packets - * @dummy: indicate a dummy station created for receiving - * EAP frames before association - * @sta: station information we share with the driver */ struct sta_info { /* General information, mostly static */ @@ -343,9 +336,6 @@ struct sta_info { unsigned int lost_packets; - /* should be right in front of sta to be in the same cache line */ - bool dummy; - /* keep last! */ struct ieee80211_sta sta; }; @@ -446,15 +436,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); -struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr); - struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr); -struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr); - static inline void for_each_sta_info_type_check(struct ieee80211_local *local, const u8 *addr, @@ -464,22 +448,6 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, } #define for_each_sta_info(local, _addr, _sta, nxt) \ - for ( /* initialise loop */ \ - _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ - /* typecheck */ \ - for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ - /* continue condition */ \ - _sta; \ - /* advance loop */ \ - _sta = nxt, \ - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ - ) \ - /* run code only if address matches and it's not a dummy sta */ \ - if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ - !_sta->dummy) - -#define for_each_sta_info_rx(local, _addr, _sta, nxt) \ for ( /* initialise loop */ \ _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ @@ -516,7 +484,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, int sta_info_insert(struct sta_info *sta); int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); int sta_info_insert_atomic(struct sta_info *sta); -int sta_info_reinsert(struct sta_info *sta); int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr); diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 14268465f1d8..a89cca3491b4 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -127,32 +127,12 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, dev_kfree_skb(skb); } -static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid) -{ - struct tid_ampdu_tx *tid_tx; - - tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); - if (!tid_tx || !tid_tx->bar_pending) - return; - - tid_tx->bar_pending = false; - ieee80211_send_bar(&sta->sdata->vif, addr, tid, tid_tx->failed_bar_ssn); -} - static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) { struct ieee80211_mgmt *mgmt = (void *) skb->data; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - if (ieee80211_is_data_qos(mgmt->frame_control)) { - struct ieee80211_hdr *hdr = (void *) skb->data; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u16 tid = qc[0] & 0xf; - - ieee80211_check_pending_bar(sta, hdr->addr1, tid); - } - if (ieee80211_is_action(mgmt->frame_control) && sdata->vif.type == NL80211_IFTYPE_STATION && mgmt->u.action.category == WLAN_CATEGORY_HT && @@ -181,18 +161,6 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) } } -static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) -{ - struct tid_ampdu_tx *tid_tx; - - tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); - if (!tid_tx) - return; - - tid_tx->failed_bar_ssn = ssn; - tid_tx->bar_pending = true; -} - /* * Use a static threshold for now, best value to be determined * by testing ... @@ -219,8 +187,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) int rates_idx = -1; bool send_to_cooked; bool acked; - struct ieee80211_bar *bar; - u16 tid; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { if (info->status.rates[i].idx < 0) { @@ -273,29 +239,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) tid = qc[0] & 0xf; ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) & IEEE80211_SCTL_SEQ); - ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, + ieee80211_send_bar(sta->sdata, hdr->addr1, tid, ssn); } - if (!acked && ieee80211_is_back_req(fc)) { - /* - * BAR failed, let's tear down the BA session as a - * last resort as some STAs (Intel 5100 on Windows) - * can get stuck when the BA window isn't flushed - * correctly. - */ - bar = (struct ieee80211_bar *) skb->data; - if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { - u16 ssn = le16_to_cpu(bar->start_seq_num); - - tid = (bar->control & - IEEE80211_BAR_CTRL_TID_INFO_MASK) >> - IEEE80211_BAR_CTRL_TID_INFO_SHIFT; - - ieee80211_set_bar_pending(sta, tid, ssn); - } - } - if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { ieee80211_handle_filtered_frame(local, sta, skb); rcu_read_unlock(); diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 7cd6c28968b2..69fd494f32f9 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1232,8 +1232,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->sta = sta_info_get(sdata, hdr->addr1); if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && - (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) && - !(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) { + (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { struct tid_ampdu_tx *tid_tx; qc = ieee80211_get_qos_ctl(hdr); @@ -1596,7 +1595,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, return; } - ieee80211_set_qos_hdr(sdata, skb); + ieee80211_set_qos_hdr(local, skb); ieee80211_tx(sdata, skb, false); rcu_read_unlock(); } @@ -1879,10 +1878,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, rcu_read_unlock(); } - /* For mesh, the use of the QoS header is mandatory */ - if (ieee80211_vif_is_mesh(&sdata->vif)) - sta_flags |= WLAN_STA_WME; - /* receiver and we are QoS enabled, use a QoS type frame */ if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) { fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); @@ -2300,23 +2295,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(sdata->vif.bss_conf.beacon_int); - mgmt->u.beacon.capab_info |= cpu_to_le16( - sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0); + mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ pos = skb_put(skb, 2); *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - if (mesh_add_srates_ie(skb, sdata) || - mesh_add_ds_params_ie(skb, sdata) || - mesh_add_ext_srates_ie(skb, sdata) || - mesh_add_rsn_ie(skb, sdata) || - mesh_add_meshid_ie(skb, sdata) || - mesh_add_meshconf_ie(skb, sdata) || - mesh_add_vendor_ies(skb, sdata)) { - pr_err("o11s: couldn't add ies!\n"); - goto out; - } + mesh_mgmt_ies_add(skb, sdata); } else { WARN_ON(1); goto out; @@ -2370,9 +2355,11 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, local = sdata->local; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for " + "pspoll template\n", sdata->name); return NULL; - + } skb_reserve(skb, local->hw.extra_tx_headroom); pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); @@ -2408,9 +2395,11 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, local = sdata->local; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "template\n", sdata->name); return NULL; - + } skb_reserve(skb, local->hw.extra_tx_headroom); nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb, @@ -2445,8 +2434,11 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + ie_ssid_len + ie_len); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for probe " + "request template\n", sdata->name); return NULL; + } skb_reserve(skb, local->hw.extra_tx_headroom); diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 4b1466d5b6a1..7a0e351a510e 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -572,6 +573,172 @@ void ieee802_11_parse_elems(u8 *start, size_t len, ieee802_11_parse_elems_crc(start, len, elems, 0, 0); } +u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc) +{ + size_t left = len; + u8 *pos = start; + bool calc_crc = filter != 0; + + memset(elems, 0, sizeof(*elems)); + elems->ie_start = start; + elems->total_len = len; + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + break; + + if (calc_crc && id < 64 && (filter & (1ULL << id))) + crc = crc32_be(crc, pos - 2, elen + 2); + + switch (id) { + case WLAN_EID_SSID: + elems->ssid = pos; + elems->ssid_len = elen; + break; + case WLAN_EID_SUPP_RATES: + elems->supp_rates = pos; + elems->supp_rates_len = elen; + break; + case WLAN_EID_FH_PARAMS: + elems->fh_params = pos; + elems->fh_params_len = elen; + break; + case WLAN_EID_DS_PARAMS: + elems->ds_params = pos; + elems->ds_params_len = elen; + break; + case WLAN_EID_CF_PARAMS: + elems->cf_params = pos; + elems->cf_params_len = elen; + break; + case WLAN_EID_TIM: + if (elen >= sizeof(struct ieee80211_tim_ie)) { + elems->tim = (void *)pos; + elems->tim_len = elen; + } + break; + case WLAN_EID_IBSS_PARAMS: + elems->ibss_params = pos; + elems->ibss_params_len = elen; + break; + case WLAN_EID_CHALLENGE: + elems->challenge = pos; + elems->challenge_len = elen; + break; + case WLAN_EID_VENDOR_SPECIFIC: + if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && + pos[2] == 0xf2) { + /* Microsoft OUI (00:50:F2) */ + + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + + if (pos[3] == 1) { + /* OUI Type 1 - WPA IE */ + elems->wpa = pos; + elems->wpa_len = elen; + } else if (elen >= 5 && pos[3] == 2) { + /* OUI Type 2 - WMM IE */ + if (pos[4] == 0) { + elems->wmm_info = pos; + elems->wmm_info_len = elen; + } else if (pos[4] == 1) { + elems->wmm_param = pos; + elems->wmm_param_len = elen; + } + } + } + break; + case WLAN_EID_RSN: + elems->rsn = pos; + elems->rsn_len = elen; + break; + case WLAN_EID_ERP_INFO: + elems->erp_info = pos; + elems->erp_info_len = elen; + break; + case WLAN_EID_EXT_SUPP_RATES: + elems->ext_supp_rates = pos; + elems->ext_supp_rates_len = elen; + break; + case WLAN_EID_HT_CAPABILITY: + if (elen >= sizeof(struct ieee80211_ht_cap)) + elems->ht_cap_elem = (void *)pos; + break; + case WLAN_EID_HT_INFORMATION: + if (elen >= sizeof(struct ieee80211_ht_info)) + elems->ht_info_elem = (void *)pos; + break; + case WLAN_EID_MESH_ID: + elems->mesh_id = pos; + elems->mesh_id_len = elen; + break; + case WLAN_EID_MESH_CONFIG: + if (elen >= sizeof(struct ieee80211_meshconf_ie)) + elems->mesh_config = (void *)pos; + break; + case WLAN_EID_PEER_LINK: + elems->peer_link = pos; + elems->peer_link_len = elen; + break; + case WLAN_EID_PREQ: + elems->preq = pos; + elems->preq_len = elen; + break; + case WLAN_EID_PREP: + elems->prep = pos; + elems->prep_len = elen; + break; + case WLAN_EID_PERR: + elems->perr = pos; + elems->perr_len = elen; + break; + case WLAN_EID_RANN: + if (elen >= sizeof(struct ieee80211_rann_ie)) + elems->rann = (void *)pos; + break; + case WLAN_EID_CHANNEL_SWITCH: + elems->ch_switch_elem = pos; + elems->ch_switch_elem_len = elen; + break; + case WLAN_EID_QUIET: + if (!elems->quiet_elem) { + elems->quiet_elem = pos; + elems->quiet_elem_len = elen; + } + elems->num_of_quiet_elem++; + break; + case WLAN_EID_COUNTRY: + elems->country_elem = pos; + elems->country_elem_len = elen; + break; + case WLAN_EID_PWR_CONSTRAINT: + elems->pwr_constr_elem = pos; + elems->pwr_constr_elem_len = elen; + break; + case WLAN_EID_TIMEOUT_INTERVAL: + elems->timeout_int = pos; + elems->timeout_int_len = elen; + break; + default: + break; + } + + left -= elen; + pos += elen; + } + + return crc; +} + void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -707,9 +874,11 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 6 + extra_len); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for auth " + "frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); @@ -862,8 +1031,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, /* FIXME: come up with a proper value */ buf = kmalloc(200 + ie_len, GFP_KERNEL); - if (!buf) + if (!buf) { + printk(KERN_DEBUG "%s: failed to allocate temporary IE " + "buffer\n", sdata->name); return NULL; + } /* * Do not send DS Channel parameter for directed probe requests @@ -1077,8 +1249,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) changed |= BSS_CHANGED_IBSS; /* fall through */ case NL80211_IFTYPE_AP: - changed |= BSS_CHANGED_SSID; - /* fall through */ case NL80211_IFTYPE_MESH_POINT: changed |= BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED; diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index 971004c9b04f..7a49532f14cb 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -83,7 +83,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, break; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: - ra = skb->data; + /* + * XXX: This is clearly broken ... but already was before, + * because ieee80211_fill_mesh_addresses() would clear A1 + * except for multicast addresses. + */ break; #endif case NL80211_IFTYPE_STATION: @@ -135,8 +139,7 @@ u16 ieee80211_downgrade_queue(struct ieee80211_local *local, return ieee802_1d_to_ac[skb->priority]; } -void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb) +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; @@ -147,11 +150,10 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - if (unlikely(sdata->local->wifi_wme_noack_test)) + if (unlikely(local->wifi_wme_noack_test)) ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; - /* qos header is 2 bytes */ + /* qos header is 2 bytes, second reserved */ *p++ = ack_policy | tid; - *p = ieee80211_vif_is_mesh(&sdata->vif) ? - (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; + *p = 0; } } diff --git a/trunk/net/mac80211/wme.h b/trunk/net/mac80211/wme.h index 34e166fbf4d4..faead6d02026 100644 --- a/trunk/net/mac80211/wme.h +++ b/trunk/net/mac80211/wme.h @@ -17,8 +17,7 @@ extern const int ieee802_1d_to_ac[8]; u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); -void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb); +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb); u16 ieee80211_downgrade_queue(struct ieee80211_local *local, struct sk_buff *skb); diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index bac34394c05e..380b9a7462b6 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -229,9 +229,11 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, wk->ie_len + /* extra IEs */ 9, /* WMM */ GFP_KERNEL); - if (!skb) + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " + "frame\n", sdata->name); return; - + } skb_reserve(skb, local->hw.extra_tx_headroom); capab = WLAN_CAPABILITY_ESS; diff --git a/trunk/net/nfc/core.c b/trunk/net/nfc/core.c index 284e2f6a14ff..b6fd4e1f2057 100644 --- a/trunk/net/nfc/core.c +++ b/trunk/net/nfc/core.c @@ -322,9 +322,7 @@ struct nfc_dev *nfc_get_device(unsigned idx) * @supported_protocols: NFC protocols supported by the device */ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - u32 supported_protocols, - int tx_headroom, - int tx_tailroom) + u32 supported_protocols) { static atomic_t dev_no = ATOMIC_INIT(0); struct nfc_dev *dev; @@ -347,8 +345,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->ops = ops; dev->supported_protocols = supported_protocols; - dev->tx_headroom = tx_headroom; - dev->tx_tailroom = tx_tailroom; spin_lock_init(&dev->targets_lock); nfc_genl_data_init(&dev->genl_data); diff --git a/trunk/net/nfc/rawsock.c b/trunk/net/nfc/rawsock.c index 9fd652a51424..52de84a55115 100644 --- a/trunk/net/nfc/rawsock.c +++ b/trunk/net/nfc/rawsock.c @@ -123,7 +123,11 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, static int rawsock_add_header(struct sk_buff *skb) { - *skb_push(skb, NFC_HEADER_SIZE) = 0; + + if (skb_cow_head(skb, 1)) + return -ENOMEM; + + *skb_push(skb, 1) = 0; return 0; } @@ -193,7 +197,6 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - struct nfc_dev *dev = nfc_rawsock(sk)->dev; struct sk_buff *skb; int rc; @@ -205,13 +208,11 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, if (sock->state != SS_CONNECTED) return -ENOTCONN; - skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE, - msg->msg_flags & MSG_DONTWAIT, &rc); + skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, + &rc); if (!skb) return rc; - skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); - rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); if (rc < 0) { kfree_skb(skb); diff --git a/trunk/net/rfkill/rfkill-regulator.c b/trunk/net/rfkill/rfkill-regulator.c index 3ca7277a3c36..18dc512a10f3 100644 --- a/trunk/net/rfkill/rfkill-regulator.c +++ b/trunk/net/rfkill/rfkill-regulator.c @@ -90,6 +90,7 @@ static int __devinit rfkill_regulator_probe(struct platform_device *pdev) pdata->type, &rfkill_regulator_ops, rfkill_data); if (rf_kill == NULL) { + dev_err(&pdev->dev, "Cannot alloc rfkill device\n"); ret = -ENOMEM; goto err_rfkill_alloc; } diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index 44cbebac25e0..645437cfc464 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -582,7 +582,7 @@ int wiphy_register(struct wiphy *wiphy) } /* set up regulatory info */ - regulatory_update(wiphy, NL80211_REGDOM_SET_BY_CORE); + wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); list_add_rcu(&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index 796a4bdf8b0d..8672e028022f 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -279,6 +279,8 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname); void ieee80211_set_bitrate_flags(struct wiphy *wiphy); +void wiphy_update_regulatory(struct wiphy *wiphy, + enum nl80211_reg_initiator setby); void cfg80211_bss_expire(struct cfg80211_registered_device *dev); void cfg80211_bss_age(struct cfg80211_registered_device *dev, diff --git a/trunk/net/wireless/lib80211_crypt_ccmp.c b/trunk/net/wireless/lib80211_crypt_ccmp.c index 755738d26bb4..dacb3b4b1bdb 100644 --- a/trunk/net/wireless/lib80211_crypt_ccmp.c +++ b/trunk/net/wireless/lib80211_crypt_ccmp.c @@ -77,6 +77,8 @@ static void *lib80211_ccmp_init(int key_idx) priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { + printk(KERN_DEBUG "lib80211_crypt_ccmp: could not allocate " + "crypto API aes\n"); priv->tfm = NULL; goto fail; } diff --git a/trunk/net/wireless/lib80211_crypt_tkip.c b/trunk/net/wireless/lib80211_crypt_tkip.c index 38734846c19e..7ea4f2b0770e 100644 --- a/trunk/net/wireless/lib80211_crypt_tkip.c +++ b/trunk/net/wireless/lib80211_crypt_tkip.c @@ -101,6 +101,7 @@ static void *lib80211_tkip_init(int key_idx) priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { + printk(KERN_DEBUG pr_fmt("could not allocate crypto API arc4\n")); priv->tx_tfm_arc4 = NULL; goto fail; } @@ -108,6 +109,7 @@ static void *lib80211_tkip_init(int key_idx) priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { + printk(KERN_DEBUG pr_fmt("could not allocate crypto API michael_mic\n")); priv->tx_tfm_michael = NULL; goto fail; } @@ -115,6 +117,7 @@ static void *lib80211_tkip_init(int key_idx) priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { + printk(KERN_DEBUG pr_fmt("could not allocate crypto API arc4\n")); priv->rx_tfm_arc4 = NULL; goto fail; } @@ -122,6 +125,7 @@ static void *lib80211_tkip_init(int key_idx) priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { + printk(KERN_DEBUG pr_fmt("could not allocate crypto API michael_mic\n")); priv->rx_tfm_michael = NULL; goto fail; } diff --git a/trunk/net/wireless/lib80211_crypt_wep.c b/trunk/net/wireless/lib80211_crypt_wep.c index c1304018fc1c..2f265e033ae2 100644 --- a/trunk/net/wireless/lib80211_crypt_wep.c +++ b/trunk/net/wireless/lib80211_crypt_wep.c @@ -50,12 +50,16 @@ static void *lib80211_wep_init(int keyidx) priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) { + printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate " + "crypto API arc4\n"); priv->tx_tfm = NULL; goto fail; } priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) { + printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate " + "crypto API arc4\n"); priv->rx_tfm = NULL; goto fail; } diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index 4423e64c7d98..5c116083eeca 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -12,7 +12,6 @@ #define MESH_HOLD_T 100 #define MESH_PATH_TIMEOUT 5000 -#define MESH_RANN_INTERVAL 5000 /* * Minimum interval between two consecutive PREQs originated by the same @@ -50,8 +49,6 @@ const struct mesh_config default_mesh_config = { .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES, .path_refresh_time = MESH_PATH_REFRESH_TIME, .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, - .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, - .dot11MeshGateAnnouncementProtocol = false, }; const struct mesh_setup default_mesh_setup = { diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 11089541bb03..080fd470fdec 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -23,12 +23,6 @@ #include "nl80211.h" #include "reg.h" -static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type); -static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, - struct genl_info *info, - struct cfg80211_crypto_settings *settings, - int cipher_limit); - static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info); static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, @@ -184,13 +178,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, - [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 }, - [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY, - .len = IEEE80211_MAX_DATA_LEN }, - [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY, - .len = IEEE80211_MAX_DATA_LEN }, - [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, - [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -233,12 +220,6 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN }, }; -static const struct nla_policy -nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { - [NL80211_ATTR_SCHED_SCAN_MATCH_SSID] = { .type = NLA_BINARY, - .len = IEEE80211_MAX_SSID_LEN }, -}; - /* ifidx get helper */ static int nl80211_get_ifidx(struct netlink_callback *cb) { @@ -722,18 +703,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.max_scan_ie_len); NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, dev->wiphy.max_sched_scan_ie_len); - NLA_PUT_U8(msg, NL80211_ATTR_MAX_MATCH_SETS, - dev->wiphy.max_match_sets); if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); - if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) - NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD); - - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) - NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT); NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -2010,10 +1984,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters params; int haveinfo = 0, err; - if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) return -EINVAL; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && @@ -2039,49 +2010,6 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (err) return err; - /* - * In theory, some of these attributes could be required for - * NEW_BEACON, but since they were not used when the command was - * originally added, keep them optional for old user space - * programs to work with drivers that do not need the additional - * information. - */ - if (info->attrs[NL80211_ATTR_SSID]) { - params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); - params.ssid_len = - nla_len(info->attrs[NL80211_ATTR_SSID]); - if (params.ssid_len == 0 || - params.ssid_len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - } - - if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { - params.hidden_ssid = nla_get_u32( - info->attrs[NL80211_ATTR_HIDDEN_SSID]); - if (params.hidden_ssid != - NL80211_HIDDEN_SSID_NOT_IN_USE && - params.hidden_ssid != - NL80211_HIDDEN_SSID_ZERO_LEN && - params.hidden_ssid != - NL80211_HIDDEN_SSID_ZERO_CONTENTS) - return -EINVAL; - } - - params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; - - if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { - params.auth_type = nla_get_u32( - info->attrs[NL80211_ATTR_AUTH_TYPE]); - if (!nl80211_valid_auth_type(params.auth_type)) - return -EINVAL; - } else - params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; - - err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, - NL80211_MAX_NR_CIPHER_SUITES); - if (err) - return err; - call = rdev->ops->add_beacon; break; case NL80211_CMD_SET_BEACON: @@ -2112,25 +2040,6 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (!haveinfo) return -EINVAL; - if (info->attrs[NL80211_ATTR_IE]) { - params.beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); - params.beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); - } - - if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { - params.proberesp_ies = - nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); - params.proberesp_ies_len = - nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); - } - - if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { - params.assocresp_ies = - nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); - params.assocresp_ies_len = - nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); - } - err = call(&rdev->wiphy, dev, ¶ms); if (!err && params.interval) wdev->beacon_interval = params.interval; @@ -2560,12 +2469,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return err; } -static struct nla_policy -nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { - [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, - [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, -}; - static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2611,33 +2514,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (parse_station_flags(info, ¶ms)) return -EINVAL; - /* parse WME attributes if sta is WME capable */ - if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && - (params.sta_flags_set & NL80211_STA_FLAG_WME) && - info->attrs[NL80211_ATTR_STA_WME]) { - struct nlattr *tb[NL80211_STA_WME_MAX + 1]; - struct nlattr *nla; - - nla = info->attrs[NL80211_ATTR_STA_WME]; - err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, - nl80211_sta_wme_policy); - if (err) - return err; - - if (tb[NL80211_STA_WME_UAPSD_QUEUES]) - params.uapsd_queues = - nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); - if (params.uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) - return -EINVAL; - - if (tb[NL80211_STA_WME_MAX_SP]) - params.max_sp = - nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); - - if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) - return -EINVAL; - } - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && @@ -3083,10 +2959,6 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, cur_params.dot11MeshHWMPnetDiameterTraversalTime); NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, cur_params.dot11MeshHWMPRootMode); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, - cur_params.dot11MeshHWMPRannInterval); - NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, - cur_params.dot11MeshGateAnnouncementProtocol); nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); @@ -3114,9 +2986,6 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, - [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, - [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, - [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, }; static const struct nla_policy @@ -3195,14 +3064,6 @@ do {\ dot11MeshHWMPRootMode, mask, NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8); - FILL_IN_MESH_PARAM_IF_SET(tb, cfg, - dot11MeshHWMPRannInterval, mask, - NL80211_MESHCONF_HWMP_RANN_INTERVAL, - nla_get_u16); - FILL_IN_MESH_PARAM_IF_SET(tb, cfg, - dot11MeshGateAnnouncementProtocol, mask, - NL80211_MESHCONF_GATE_ANNOUNCEMENTS, - nla_get_u8); if (mask_out) *mask_out = mask; @@ -3646,11 +3507,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, struct net_device *dev = info->user_ptr[1]; struct nlattr *attr; struct wiphy *wiphy; - int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i; + int err, tmp, n_ssids = 0, n_channels, i; u32 interval; enum ieee80211_band band; size_t ie_len; - struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || !rdev->ops->sched_scan_start) @@ -3689,15 +3549,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, if (n_ssids > wiphy->max_sched_scan_ssids) return -EINVAL; - if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) - nla_for_each_nested(attr, - info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], - tmp) - n_match_sets++; - - if (n_match_sets > wiphy->max_match_sets) - return -EINVAL; - if (info->attrs[NL80211_ATTR_IE]) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); else @@ -3715,7 +3566,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, request = kzalloc(sizeof(*request) + sizeof(*request->ssids) * n_ssids - + sizeof(*request->match_sets) * n_match_sets + sizeof(*request->channels) * n_channels + ie_len, GFP_KERNEL); if (!request) { @@ -3733,18 +3583,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, request->ie = (void *)(request->channels + n_channels); } - if (n_match_sets) { - if (request->ie) - request->match_sets = (void *)(request->ie + ie_len); - else if (request->ssids) - request->match_sets = - (void *)(request->ssids + n_ssids); - else - request->match_sets = - (void *)(request->channels + n_channels); - } - request->n_match_sets = n_match_sets; - i = 0; if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { /* user specified, bail out if channel not found */ @@ -3809,31 +3647,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, } } - i = 0; - if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { - nla_for_each_nested(attr, - info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], - tmp) { - struct nlattr *ssid; - - nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, - nla_data(attr), nla_len(attr), - nl80211_match_policy); - ssid = tb[NL80211_ATTR_SCHED_SCAN_MATCH_SSID]; - if (ssid) { - if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { - err = -EINVAL; - goto out_free; - } - memcpy(request->match_sets[i].ssid.ssid, - nla_data(ssid), nla_len(ssid)); - request->match_sets[i].ssid.ssid_len = - nla_len(ssid); - } - i++; - } - } - if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); memcpy((void *)request->ie, diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 18fc37b6f2bd..9f3aa5cabdef 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -751,10 +751,9 @@ static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, chan->center_freq, KHZ_TO_MHZ(desired_bw_khz)); - REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n", + REG_DBG_PRINT("%d KHz - %d KHz @ KHz), (%s mBi, %d mBm)\n", freq_range->start_freq_khz, freq_range->end_freq_khz, - freq_range->max_bandwidth_khz, max_antenna_gain, power_rule->max_eirp); } @@ -911,6 +910,14 @@ static bool ignore_reg_update(struct wiphy *wiphy, return false; } +static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) +{ + struct cfg80211_registered_device *rdev; + + list_for_each_entry(rdev, &cfg80211_rdev_list, list) + wiphy_update_regulatory(&rdev->wiphy, initiator); +} + static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, struct reg_beacon *reg_beacon) @@ -1110,13 +1117,11 @@ static void reg_process_ht_flags(struct wiphy *wiphy) } -static void wiphy_update_regulatory(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +void wiphy_update_regulatory(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { enum ieee80211_band band; - assert_reg_lock(); - if (ignore_reg_update(wiphy, initiator)) return; @@ -1131,22 +1136,6 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, wiphy->reg_notifier(wiphy, last_request); } -void regulatory_update(struct wiphy *wiphy, - enum nl80211_reg_initiator setby) -{ - mutex_lock(®_mutex); - wiphy_update_regulatory(wiphy, setby); - mutex_unlock(®_mutex); -} - -static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) -{ - struct cfg80211_registered_device *rdev; - - list_for_each_entry(rdev, &cfg80211_rdev_list, list) - wiphy_update_regulatory(&rdev->wiphy, initiator); -} - static void handle_channel_custom(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx, diff --git a/trunk/net/wireless/reg.h b/trunk/net/wireless/reg.h index 4a56799d868d..b67d1c3a2fb9 100644 --- a/trunk/net/wireless/reg.h +++ b/trunk/net/wireless/reg.h @@ -16,8 +16,6 @@ void regulatory_exit(void); int set_regdom(const struct ieee80211_regdomain *rd); -void regulatory_update(struct wiphy *wiphy, enum nl80211_reg_initiator setby); - /** * regulatory_hint_found_beacon - hints a beacon was found on a channel * @wiphy: the wireless device where the beacon was found on diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 39dbf4ad7ca1..be75a3a0424e 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include "core.h" @@ -513,9 +512,10 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, if (head_need) skb_orphan(skb); - if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) + if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) { + pr_err("failed to reallocate Tx buffer\n"); return -ENOMEM; - + } skb->truesize += head_need; } @@ -1044,170 +1044,3 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, return 0; } - -u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, - struct ieee802_11_elems *elems, - u64 filter, u32 crc) -{ - size_t left = len; - u8 *pos = start; - bool calc_crc = filter != 0; - - memset(elems, 0, sizeof(*elems)); - elems->ie_start = start; - elems->total_len = len; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) - break; - - if (calc_crc && id < 64 && (filter & (1ULL << id))) - crc = crc32_be(crc, pos - 2, elen + 2); - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - if (elen >= sizeof(struct ieee80211_tim_ie)) { - elems->tim = (void *)pos; - elems->tim_len = elen; - } - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && - pos[2] == 0xf2) { - /* Microsoft OUI (00:50:F2) */ - - if (calc_crc) - crc = crc32_be(crc, pos - 2, elen + 2); - - if (pos[3] == 1) { - /* OUI Type 1 - WPA IE */ - elems->wpa = pos; - elems->wpa_len = elen; - } else if (elen >= 5 && pos[3] == 2) { - /* OUI Type 2 - WMM IE */ - if (pos[4] == 0) { - elems->wmm_info = pos; - elems->wmm_info_len = elen; - } else if (pos[4] == 1) { - elems->wmm_param = pos; - elems->wmm_param_len = elen; - } - } - } - break; - case WLAN_EID_RSN: - elems->rsn = pos; - elems->rsn_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_HT_CAPABILITY: - if (elen >= sizeof(struct ieee80211_ht_cap)) - elems->ht_cap_elem = (void *)pos; - break; - case WLAN_EID_HT_INFORMATION: - if (elen >= sizeof(struct ieee80211_ht_info)) - elems->ht_info_elem = (void *)pos; - break; - case WLAN_EID_MESH_ID: - elems->mesh_id = pos; - elems->mesh_id_len = elen; - break; - case WLAN_EID_MESH_CONFIG: - if (elen >= sizeof(struct ieee80211_meshconf_ie)) - elems->mesh_config = (void *)pos; - break; - case WLAN_EID_PEER_MGMT: - elems->peering = pos; - elems->peering_len = elen; - break; - case WLAN_EID_PREQ: - elems->preq = pos; - elems->preq_len = elen; - break; - case WLAN_EID_PREP: - elems->prep = pos; - elems->prep_len = elen; - break; - case WLAN_EID_PERR: - elems->perr = pos; - elems->perr_len = elen; - break; - case WLAN_EID_RANN: - if (elen >= sizeof(struct ieee80211_rann_ie)) - elems->rann = (void *)pos; - break; - case WLAN_EID_CHANNEL_SWITCH: - elems->ch_switch_elem = pos; - elems->ch_switch_elem_len = elen; - break; - case WLAN_EID_QUIET: - if (!elems->quiet_elem) { - elems->quiet_elem = pos; - elems->quiet_elem_len = elen; - } - elems->num_of_quiet_elem++; - break; - case WLAN_EID_COUNTRY: - elems->country_elem = pos; - elems->country_elem_len = elen; - break; - case WLAN_EID_PWR_CONSTRAINT: - elems->pwr_constr_elem = pos; - elems->pwr_constr_elem_len = elen; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - elems->timeout_int = pos; - elems->timeout_int_len = elen; - break; - default: - break; - } - - left -= elen; - pos += elen; - } - - return crc; -} -EXPORT_SYMBOL(ieee802_11_parse_elems_crc);