Merge tag 'wireless-drivers-next-for-davem-2015-06-03' of git://git.kernel.org/pub...
authorDavid S. Miller <davem@davemloft.net>
Thu, 4 Jun 2015 06:44:57 +0000 (23:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 4 Jun 2015 06:44:57 +0000 (23:44 -0700)
Kalle Valo says:

====================
new driver mt7601u for MediaTek Wi-Fi devices MT7601U

ath10k:

* qca6174 power consumption improvements, enable ASPM etc (Michal)

wil6210:

* support Wi-Fi Simple Configuration in STA mode

iwlwifi:

* a few fixes (re-enablement of interrupts for certain new
  platforms that have special power states)
* Rework completely the RBD allocation model towards new
  multi RX hardware.
* cleanups
* scan reworks continuation (Luca)

mwifiex:

* improve firmware debug functionality

rtlwifi:

* update regulatory database

brcmfmac:

* cleanup and new feature support in PCIe code
* alternative nvram loading for router support
====================

Conflicts:
drivers/net/wireless/iwlwifi/Kconfig

Trivial conflict in iwlwifi Kconfig, two commits adding
the same two chip numbers to the help text, but order
transposed.

Signed-off-by: David S. Miller <davem@davemloft.net>
155 files changed:
MAINTAINERS
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/adm8211.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/spectral.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9002_phy.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/ath/wil6210/Makefile
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/netdev.c
drivers/net/wireless/ath/wil6210/pcie_bus.c
drivers/net/wireless/ath/wil6210/pmc.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/pmc.h [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/txrx.h
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wmi.c
drivers/net/wireless/ath/wil6210/wmi.h
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/commonring.c
drivers/net/wireless/brcm80211/brcmfmac/firmware.c
drivers/net/wireless/brcm80211/brcmfmac/flowring.c
drivers/net/wireless/brcm80211/brcmfmac/flowring.h
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
drivers/net/wireless/brcm80211/brcmfmac/of.c
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-devtrace-iwlwifi.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/iwl-trans.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mediatek/Kconfig [new file with mode: 0644]
drivers/net/wireless/mediatek/Makefile [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/Kconfig [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/Makefile [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/core.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/debugfs.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/dma.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/dma.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/eeprom.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/eeprom.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/init.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/initvals.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/initvals_phy.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/mac.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/mac.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/main.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/mcu.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/mcu.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/mt7601u.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/phy.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/regs.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/trace.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/trace.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/tx.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/usb.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/usb.h [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/util.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt7601u/util.h [new file with mode: 0644]
drivers/net/wireless/mwifiex/11h.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/Kconfig
drivers/net/wireless/mwifiex/README
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cfp.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/mwifiex/ethtool.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/ioctl.h
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwifiex/sta_tx.c
drivers/net/wireless/mwifiex/tdls.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_cmd.c
drivers/net/wireless/mwifiex/uap_event.c
drivers/net/wireless/mwifiex/uap_txrx.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rtlwifi/Kconfig
drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c
drivers/net/wireless/rtlwifi/regd.c
drivers/net/wireless/rtlwifi/regd.h
drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c
drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
drivers/net/wireless/rtlwifi/rtl8723be/hw.c
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
include/linux/bcma/bcma.h

index a798534a2ab13858c1ee85735989b6747d546e5c..3a4b7cbbaa72e1446688e4d14e1dae68a7f5b1bc 100644 (file)
@@ -6372,6 +6372,12 @@ F:       include/uapi/linux/meye.h
 F:     include/uapi/linux/ivtv*
 F:     include/uapi/linux/uvcvideo.h
 
+MEDIATEK MT7601U WIRELESS LAN DRIVER
+M:     Jakub Kicinski <kubakici@wp.pl>
+L:     linux-wireless@vger.kernel.org
+S:     Maintained
+F:     drivers/net/wireless/mediatek/mt7601u/
+
 MEGARAID SCSI/SAS DRIVERS
 M:     Kashyap Desai <kashyap.desai@avagotech.com>
 M:     Sumit Saxena <sumit.saxena@avagotech.com>
index 16604bdf5197ea81031484c2d3deefa5d0aae020..a63ab2e831054b372b551788e9106ebf29bc925c 100644 (file)
@@ -277,6 +277,7 @@ source "drivers/net/wireless/libertas/Kconfig"
 source "drivers/net/wireless/orinoco/Kconfig"
 source "drivers/net/wireless/p54/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
+source "drivers/net/wireless/mediatek/Kconfig"
 source "drivers/net/wireless/rtlwifi/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
index 0c88916867187817ea08f43c4d69cbaf86d28246..6b9e729dd8acbf0af1a545109b0b304d400e93d4 100644 (file)
@@ -45,6 +45,8 @@ obj-$(CONFIG_IWLWIFI) += iwlwifi/
 obj-$(CONFIG_IWLEGACY) += iwlegacy/
 obj-$(CONFIG_RT2X00)   += rt2x00/
 
+obj-$(CONFIG_WL_MEDIATEK)      += mediatek/
+
 obj-$(CONFIG_P54_COMMON)       += p54/
 
 obj-$(CONFIG_ATH_CARDS)                += ath/
index 413528295d72abb4b331e834403f71a4059a47fb..8c283fcd843d3c33c0fda7f1753d11d54e0a2bbc 100644 (file)
@@ -1098,14 +1098,18 @@ static void adm8211_hw_init(struct ieee80211_hw *dev)
                pci_read_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, &cline);
 
                switch (cline) {
-               case  0x8: reg |= (0x1 << 14);
-                          break;
-               case 0x16: reg |= (0x2 << 14);
-                          break;
-               case 0x32: reg |= (0x3 << 14);
-                          break;
-                 default: reg |= (0x0 << 14);
-                          break;
+               case  0x8:
+                       reg |= (0x1 << 14);
+                       break;
+               case 0x10:
+                       reg |= (0x2 << 14);
+                       break;
+               case 0x20:
+                       reg |= (0x3 << 14);
+                       break;
+               default:
+                       reg |= (0x0 << 14);
+                       break;
                }
        }
 
index 987b266278a85915eb0a1936f9c5010386459cf9..bcccae19325d8f77da713a37956514ee5f97c1b9 100644 (file)
@@ -387,7 +387,9 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
 
-       if (!skip_otp && result != 0) {
+       if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
+                                  ar->fw_features))
+           && result != 0) {
                ath10k_err(ar, "otp calibration failed: %d", result);
                return -EINVAL;
        }
index 8444adf42195da94ddbbead4a34018bc4f119714..70fcdc9c27587593046f1aeab8fd3b68b2d74364 100644 (file)
@@ -460,6 +460,14 @@ enum ath10k_fw_features {
         */
        ATH10K_FW_FEATURE_WOWLAN_SUPPORT = 6,
 
+       /* Don't trust error code from otp.bin */
+       ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
+
+       /* Some firmware revisions pad 4th hw address to 4 byte boundary making
+        * it 8 bytes long in Native Wifi Rx decap.
+        */
+       ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
+
        /* keep last */
        ATH10K_FW_FEATURE_COUNT,
 };
index a12b8323f9f1000ac9e139ee23d52e03f71ac13a..53bd6a19eab6215b6108077c7407de6f2bac1d30 100644 (file)
@@ -36,6 +36,7 @@ enum ath10k_debug_mask {
        ATH10K_DBG_REGULATORY   = 0x00000800,
        ATH10K_DBG_TESTMODE     = 0x00001000,
        ATH10K_DBG_WMI_PRINT    = 0x00002000,
+       ATH10K_DBG_PCI_PS       = 0x00004000,
        ATH10K_DBG_ANY          = 0xffffffff,
 };
 
index b26e32f42656358cfab81f80b4e3e46d0d8b3b50..89eb16b30fc42479a3b1c11a7b9b3fd88c043490 100644 (file)
@@ -965,10 +965,16 @@ static void ath10k_process_rx(struct ath10k *ar,
        ieee80211_rx(ar->hw, skb);
 }
 
-static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr)
+static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
+                                     struct ieee80211_hdr *hdr)
 {
-       /* nwifi header is padded to 4 bytes. this fixes 4addr rx */
-       return round_up(ieee80211_hdrlen(hdr->frame_control), 4);
+       int len = ieee80211_hdrlen(hdr->frame_control);
+
+       if (!test_bit(ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
+                     ar->fw_features))
+               len = round_up(len, 4);
+
+       return len;
 }
 
 static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
@@ -1067,7 +1073,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
 
        /* pull decapped header and copy SA & DA */
        hdr = (struct ieee80211_hdr *)msdu->data;
-       hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+       hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
        ether_addr_copy(da, ieee80211_get_DA(hdr));
        ether_addr_copy(sa, ieee80211_get_SA(hdr));
        skb_pull(msdu, hdr_len);
index 539b2b62b58a5e2ae745a52505f029ddd7d42298..0ed422ae46a487e612508de17bfbbfe662749a0f 100644 (file)
@@ -1708,7 +1708,14 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
                enable_ps = false;
        }
 
-       if (enable_ps) {
+       if (!arvif->is_started) {
+               /* mac80211 can update vif powersave state while disconnected.
+                * Firmware doesn't behave nicely and consumes more power than
+                * necessary if PS is disabled on a non-started vdev. Hence
+                * force-enable PS for non-running vdevs.
+                */
+               psmode = WMI_STA_PS_MODE_ENABLED;
+       } else if (enable_ps) {
                psmode = WMI_STA_PS_MODE_ENABLED;
                param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
 
index 969a1231800e43a06ed96cd36602355cdb910016..17a060e8efa2250bbe8d9d63c0eb104fa5282953 100644 (file)
@@ -330,6 +330,205 @@ static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
        },
 };
 
+static bool ath10k_pci_is_awake(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 val = ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
+                          RTC_STATE_ADDRESS);
+
+       return RTC_STATE_V_GET(val) == RTC_STATE_V_ON;
+}
+
+static void __ath10k_pci_wake(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       lockdep_assert_held(&ar_pci->ps_lock);
+
+       ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake reg refcount %lu awake %d\n",
+                  ar_pci->ps_wake_refcount, ar_pci->ps_awake);
+
+       iowrite32(PCIE_SOC_WAKE_V_MASK,
+                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
+                 PCIE_SOC_WAKE_ADDRESS);
+}
+
+static void __ath10k_pci_sleep(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       lockdep_assert_held(&ar_pci->ps_lock);
+
+       ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep reg refcount %lu awake %d\n",
+                  ar_pci->ps_wake_refcount, ar_pci->ps_awake);
+
+       iowrite32(PCIE_SOC_WAKE_RESET,
+                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
+                 PCIE_SOC_WAKE_ADDRESS);
+       ar_pci->ps_awake = false;
+}
+
+static int ath10k_pci_wake_wait(struct ath10k *ar)
+{
+       int tot_delay = 0;
+       int curr_delay = 5;
+
+       while (tot_delay < PCIE_WAKE_TIMEOUT) {
+               if (ath10k_pci_is_awake(ar))
+                       return 0;
+
+               udelay(curr_delay);
+               tot_delay += curr_delay;
+
+               if (curr_delay < 50)
+                       curr_delay += 5;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int ath10k_pci_wake(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&ar_pci->ps_lock, flags);
+
+       ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n",
+                  ar_pci->ps_wake_refcount, ar_pci->ps_awake);
+
+       /* This function can be called very frequently. To avoid excessive
+        * CPU stalls for MMIO reads use a cache var to hold the device state.
+        */
+       if (!ar_pci->ps_awake) {
+               __ath10k_pci_wake(ar);
+
+               ret = ath10k_pci_wake_wait(ar);
+               if (ret == 0)
+                       ar_pci->ps_awake = true;
+       }
+
+       if (ret == 0) {
+               ar_pci->ps_wake_refcount++;
+               WARN_ON(ar_pci->ps_wake_refcount == 0);
+       }
+
+       spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+
+       return ret;
+}
+
+static void ath10k_pci_sleep(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ar_pci->ps_lock, flags);
+
+       ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n",
+                  ar_pci->ps_wake_refcount, ar_pci->ps_awake);
+
+       if (WARN_ON(ar_pci->ps_wake_refcount == 0))
+               goto skip;
+
+       ar_pci->ps_wake_refcount--;
+
+       mod_timer(&ar_pci->ps_timer, jiffies +
+                 msecs_to_jiffies(ATH10K_PCI_SLEEP_GRACE_PERIOD_MSEC));
+
+skip:
+       spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+}
+
+static void ath10k_pci_ps_timer(unsigned long ptr)
+{
+       struct ath10k *ar = (void *)ptr;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ar_pci->ps_lock, flags);
+
+       ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps timer refcount %lu awake %d\n",
+                  ar_pci->ps_wake_refcount, ar_pci->ps_awake);
+
+       if (ar_pci->ps_wake_refcount > 0)
+               goto skip;
+
+       __ath10k_pci_sleep(ar);
+
+skip:
+       spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+}
+
+static void ath10k_pci_sleep_sync(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       unsigned long flags;
+
+       del_timer_sync(&ar_pci->ps_timer);
+
+       spin_lock_irqsave(&ar_pci->ps_lock, flags);
+       WARN_ON(ar_pci->ps_wake_refcount > 0);
+       __ath10k_pci_sleep(ar);
+       spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
+}
+
+void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
+
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wake target for write32 of 0x%08x at 0x%08x: %d\n",
+                           value, offset, ret);
+               return;
+       }
+
+       iowrite32(value, ar_pci->mem + offset);
+       ath10k_pci_sleep(ar);
+}
+
+u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 val;
+       int ret;
+
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wake target for read32 at 0x%08x: %d\n",
+                           offset, ret);
+               return 0xffffffff;
+       }
+
+       val = ioread32(ar_pci->mem + offset);
+       ath10k_pci_sleep(ar);
+
+       return val;
+}
+
+u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
+{
+       return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
+}
+
+void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
+}
+
+u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
+{
+       return ath10k_pci_read32(ar, PCIE_LOCAL_BASE_ADDRESS + addr);
+}
+
+void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+       ath10k_pci_write32(ar, PCIE_LOCAL_BASE_ADDRESS + addr, val);
+}
+
 static bool ath10k_pci_irq_pending(struct ath10k *ar)
 {
        u32 cause;
@@ -793,60 +992,6 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value)
        return ath10k_pci_diag_write_mem(ar, address, &val, sizeof(val));
 }
 
-static bool ath10k_pci_is_awake(struct ath10k *ar)
-{
-       u32 val = ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS);
-
-       return RTC_STATE_V_GET(val) == RTC_STATE_V_ON;
-}
-
-static int ath10k_pci_wake_wait(struct ath10k *ar)
-{
-       int tot_delay = 0;
-       int curr_delay = 5;
-
-       while (tot_delay < PCIE_WAKE_TIMEOUT) {
-               if (ath10k_pci_is_awake(ar))
-                       return 0;
-
-               udelay(curr_delay);
-               tot_delay += curr_delay;
-
-               if (curr_delay < 50)
-                       curr_delay += 5;
-       }
-
-       return -ETIMEDOUT;
-}
-
-/* The rule is host is forbidden from accessing device registers while it's
- * asleep. Currently ath10k_pci_wake() and ath10k_pci_sleep() calls aren't
- * balanced and the device is kept awake all the time. This is intended for a
- * simpler solution for the following problems:
- *
- *   * device can enter sleep during s2ram without the host knowing,
- *
- *   * irq handlers access registers which is a problem if other device asserts
- *     a shared irq line when ath10k is between hif_power_down() and
- *     hif_power_up().
- *
- * FIXME: If power consumption is a concern (and there are *real* gains) then a
- * refcounted wake/sleep needs to be implemented.
- */
-
-static int ath10k_pci_wake(struct ath10k *ar)
-{
-       ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
-                              PCIE_SOC_WAKE_V_MASK);
-       return ath10k_pci_wake_wait(ar);
-}
-
-static void ath10k_pci_sleep(struct ath10k *ar)
-{
-       ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
-                              PCIE_SOC_WAKE_RESET);
-}
-
 /* Called by lower (CE) layer when a send to Target completes. */
 static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
 {
@@ -1227,11 +1372,15 @@ static void ath10k_pci_irq_enable(struct ath10k *ar)
 
 static int ath10k_pci_hif_start(struct ath10k *ar)
 {
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
 
        ath10k_pci_irq_enable(ar);
        ath10k_pci_rx_post(ar);
 
+       pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+                                  ar_pci->link_ctl);
+
        return 0;
 }
 
@@ -1344,6 +1493,9 @@ static void ath10k_pci_flush(struct ath10k *ar)
 
 static void ath10k_pci_hif_stop(struct ath10k *ar)
 {
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       unsigned long flags;
+
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
 
        /* Most likely the device has HTT Rx ring configured. The only way to
@@ -1362,6 +1514,10 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
        ath10k_pci_irq_disable(ar);
        ath10k_pci_irq_sync(ar);
        ath10k_pci_flush(ar);
+
+       spin_lock_irqsave(&ar_pci->ps_lock, flags);
+       WARN_ON(ar_pci->ps_wake_refcount > 0);
+       spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
 }
 
 static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
@@ -1981,15 +2137,15 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
 
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
 
-       ret = ath10k_pci_wake(ar);
-       if (ret) {
-               ath10k_err(ar, "failed to wake up target: %d\n", ret);
-               return ret;
-       }
+       pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+                                 &ar_pci->link_ctl);
+       pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+                                  ar_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
 
        /*
         * Bring the target up cleanly.
@@ -2037,7 +2193,6 @@ err_ce:
        ath10k_pci_ce_deinit(ar);
 
 err_sleep:
-       ath10k_pci_sleep(ar);
        return ret;
 }
 
@@ -2054,7 +2209,12 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
 
 static int ath10k_pci_hif_suspend(struct ath10k *ar)
 {
-       ath10k_pci_sleep(ar);
+       /* The grace timer can still be counting down and ar->ps_awake be true.
+        * It is known that the device may be asleep after resuming regardless
+        * of the SoC powersave state before suspending. Hence make sure the
+        * device is asleep before proceeding.
+        */
+       ath10k_pci_sleep_sync(ar);
 
        return 0;
 }
@@ -2064,13 +2224,6 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        struct pci_dev *pdev = ar_pci->pdev;
        u32 val;
-       int ret;
-
-       ret = ath10k_pci_wake(ar);
-       if (ret) {
-               ath10k_err(ar, "failed to wake device up on resume: %d\n", ret);
-               return ret;
-       }
 
        /* Suspend/Resume resets the PCI configuration space, so we have to
         * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
@@ -2081,7 +2234,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
        if ((val & 0x0000ff00) != 0)
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
-       return ret;
+       return 0;
 }
 #endif
 
@@ -2175,13 +2328,6 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
 {
        struct ath10k *ar = arg;
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int ret;
-
-       ret = ath10k_pci_wake(ar);
-       if (ret) {
-               ath10k_warn(ar, "failed to wake device up on irq: %d\n", ret);
-               return IRQ_NONE;
-       }
 
        if (ar_pci->num_msi_intrs == 0) {
                if (!ath10k_pci_irq_pending(ar))
@@ -2502,7 +2648,6 @@ static int ath10k_pci_claim(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        struct pci_dev *pdev = ar_pci->pdev;
-       u32 lcr_val;
        int ret;
 
        pci_set_drvdata(pdev, ar);
@@ -2536,10 +2681,6 @@ static int ath10k_pci_claim(struct ath10k *ar)
 
        pci_set_master(pdev);
 
-       /* Workaround: Disable ASPM */
-       pci_read_config_dword(pdev, 0x80, &lcr_val);
-       pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00));
-
        /* Arrange for access to Target SoC registers. */
        ar_pci->mem = pci_iomap(pdev, BAR_NUM, 0);
        if (!ar_pci->mem) {
@@ -2633,8 +2774,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                          pdev->subsystem_vendor, pdev->subsystem_device);
 
        spin_lock_init(&ar_pci->ce_lock);
+       spin_lock_init(&ar_pci->ps_lock);
+
        setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
                    (unsigned long)ar);
+       setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer,
+                   (unsigned long)ar);
 
        ret = ath10k_pci_claim(ar);
        if (ret) {
@@ -2642,12 +2787,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                goto err_core_destroy;
        }
 
-       ret = ath10k_pci_wake(ar);
-       if (ret) {
-               ath10k_err(ar, "failed to wake up: %d\n", ret);
-               goto err_release;
-       }
-
        ret = ath10k_pci_alloc_pipes(ar);
        if (ret) {
                ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
@@ -2711,9 +2850,6 @@ err_free_pipes:
        ath10k_pci_free_pipes(ar);
 
 err_sleep:
-       ath10k_pci_sleep(ar);
-
-err_release:
        ath10k_pci_release(ar);
 
 err_core_destroy:
@@ -2743,6 +2879,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
        ath10k_pci_deinit_irq(ar);
        ath10k_pci_ce_deinit(ar);
        ath10k_pci_free_pipes(ar);
+       ath10k_pci_sleep_sync(ar);
        ath10k_pci_release(ar);
        ath10k_core_destroy(ar);
 }
index bddf54320160d91c8f21fd9982c54e123e3d3881..d7696ddc03c42b2b2622913f9c42674f22f84039 100644 (file)
@@ -185,6 +185,41 @@ struct ath10k_pci {
        /* Map CE id to ce_state */
        struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
        struct timer_list rx_post_retry;
+
+       /* Due to HW quirks it is recommended to disable ASPM during device
+        * bootup. To do that the original PCI-E Link Control is stored before
+        * device bootup is executed and re-programmed later.
+        */
+       u16 link_ctl;
+
+       /* Protects ps_awake and ps_wake_refcount */
+       spinlock_t ps_lock;
+
+       /* The device has a special powersave-oriented register. When device is
+        * considered asleep it drains less power and driver is forbidden from
+        * accessing most MMIO registers. If host were to access them without
+        * waking up the device might scribble over host memory or return
+        * 0xdeadbeef readouts.
+        */
+       unsigned long ps_wake_refcount;
+
+       /* Waking up takes some time (up to 2ms in some cases) so it can be bad
+        * for latency. To mitigate this the device isn't immediately allowed
+        * to sleep after all references are undone - instead there's a grace
+        * period after which the powersave register is updated unless some
+        * activity to/from device happened in the meantime.
+        *
+        * Also see comments on ATH10K_PCI_SLEEP_GRACE_PERIOD_MSEC.
+        */
+       struct timer_list ps_timer;
+
+       /* MMIO registers are used to communicate with the device. With
+        * intensive traffic accessing powersave register would be a bit
+        * wasteful overhead and would needlessly stall CPU. It is far more
+        * efficient to rely on a variable in RAM and update it only upon
+        * powersave register state changes.
+        */
+       bool ps_awake;
 };
 
 static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
@@ -209,61 +244,25 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
  * for this device; but that's not guaranteed.
  */
 #define TARG_CPU_SPACE_TO_CE_SPACE(ar, pci_addr, addr)                 \
-       (((ioread32((pci_addr)+(SOC_CORE_BASE_ADDRESS|                  \
+       (((ath10k_pci_read32(ar, (SOC_CORE_BASE_ADDRESS |               \
          CORE_CTRL_ADDRESS)) & 0x7ff) << 21) |                         \
         0x100000 | ((addr) & 0xfffff))
 
 /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
 #define DIAG_ACCESS_CE_TIMEOUT_MS 10
 
-/* Target exposes its registers for direct access. However before host can
- * access them it needs to make sure the target is awake (ath10k_pci_wake,
- * ath10k_pci_wake_wait, ath10k_pci_is_awake). Once target is awake it won't go
- * to sleep unless host tells it to (ath10k_pci_sleep).
- *
- * If host tries to access target registers without waking it up it can
- * scribble over host memory.
- *
- * If target is asleep waking it up may take up to even 2ms.
- */
-
-static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
-                                     u32 value)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
-       iowrite32(value, ar_pci->mem + offset);
-}
-
-static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
-       return ioread32(ar_pci->mem + offset);
-}
-
-static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
-{
-       return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
-}
-
-static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
-{
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
-}
-
-static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
-       return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-}
+void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value);
+void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val);
+void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val);
 
-static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+u32 ath10k_pci_read32(struct ath10k *ar, u32 offset);
+u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr);
+u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr);
 
-       iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-}
+/* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too
+ * frequently. To avoid this put SoC to sleep after a very conservative grace
+ * period. Adjust with great care.
+ */
+#define ATH10K_PCI_SLEEP_GRACE_PERIOD_MSEC 60
 
 #endif /* _PCI_H_ */
index d22addf6118b832501647c07c39cb56338542bc9..8dcd424aa5029965ffa5d2a2fb07067e9a54ce61 100644 (file)
@@ -519,9 +519,12 @@ int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
 
 int ath10k_spectral_create(struct ath10k *ar)
 {
+       /* The buffer size covers whole channels in dual bands up to 128 bins.
+        * Scan with bigger than 128 bins needs to be run on single band each.
+        */
        ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
                                                     ar->debug.debugfs_phy,
-                                                    1024, 256,
+                                                    1140, 2500,
                                                     &rfs_spec_scan_cb, NULL);
        debugfs_create_file("spectral_scan_ctl",
                            S_IRUSR | S_IWUSR,
index ebaa096cf200c7968b4b5b5ae73944d8c58c1309..0fabe689179c8a8ab3d150bada5f50bc4300a6a2 100644 (file)
@@ -1645,10 +1645,10 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
 
                survey = &ar->survey[idx];
                survey->time = WMI_CHAN_INFO_MSEC(cycle_count);
-               survey->time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
+               survey->time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count);
                survey->noise = noise_floor;
                survey->filled = SURVEY_INFO_TIME |
-                                SURVEY_INFO_TIME_RX |
+                                SURVEY_INFO_TIME_BUSY |
                                 SURVEY_INFO_NOISE_DBM;
        }
 
index 6c23d279525f5dfa8671342b3c30b25163b6e0ba..8f8793004b9f021c7f689e13dabcf32f10e2c3a0 100644 (file)
@@ -254,86 +254,25 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
        return 0;
 }
 
-/**
- * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios
- * @ah: atheros hardware structure
- * @chan:
- *
- * For non single-chip solutions. Converts to baseband spur frequency given the
- * input channel frequency and compute register settings below.
- */
-static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
-                                   struct ath9k_channel *chan)
+void ar5008_hw_cmn_spur_mitigate(struct ath_hw *ah,
+                         struct ath9k_channel *chan, int bin)
 {
-       int bb_spur = AR_NO_SPUR;
-       int bin, cur_bin;
-       int spur_freq_sd;
-       int spur_delta_phase;
-       int denominator;
+       int cur_bin;
        int upper, lower, cur_vit_mask;
-       int tmp, new;
        int i;
-       static int pilot_mask_reg[4] = {
+       int8_t mask_m[123];
+       int8_t mask_p[123];
+       int8_t mask_amt;
+       int tmp_mask;
+       static const int pilot_mask_reg[4] = {
                AR_PHY_TIMING7, AR_PHY_TIMING8,
                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
        };
-       static int chan_mask_reg[4] = {
+       static const int chan_mask_reg[4] = {
                AR_PHY_TIMING9, AR_PHY_TIMING10,
                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
        };
-       static int inc[4] = { 0, 100, 0, 0 };
-
-       int8_t mask_m[123];
-       int8_t mask_p[123];
-       int8_t mask_amt;
-       int tmp_mask;
-       int cur_bb_spur;
-       bool is2GHz = IS_CHAN_2GHZ(chan);
-
-       memset(&mask_m, 0, sizeof(int8_t) * 123);
-       memset(&mask_p, 0, sizeof(int8_t) * 123);
-
-       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
-               if (AR_NO_SPUR == cur_bb_spur)
-                       break;
-               cur_bb_spur = cur_bb_spur - (chan->channel * 10);
-               if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
-                       bb_spur = cur_bb_spur;
-                       break;
-               }
-       }
-
-       if (AR_NO_SPUR == bb_spur)
-               return;
-
-       bin = bb_spur * 32;
-
-       tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
-       new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
-                    AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
-                    AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
-                    AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
-
-       REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
-
-       new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
-              AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
-              AR_PHY_SPUR_REG_MASK_RATE_SELECT |
-              AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
-              SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
-       REG_WRITE(ah, AR_PHY_SPUR_REG, new);
-
-       spur_delta_phase = ((bb_spur * 524288) / 100) &
-               AR_PHY_TIMING11_SPUR_DELTA_PHASE;
-
-       denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
-       spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
-
-       new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
-              SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
-              SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
-       REG_WRITE(ah, AR_PHY_TIMING11, new);
+       static const int inc[4] = { 0, 100, 0, 0 };
 
        cur_bin = -6000;
        upper = bin + 100;
@@ -343,6 +282,7 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
                int pilot_mask = 0;
                int chan_mask = 0;
                int bp = 0;
+
                for (bp = 0; bp < 30; bp++) {
                        if ((cur_bin > lower) && (cur_bin < upper)) {
                                pilot_mask = pilot_mask | 0x1 << bp;
@@ -361,7 +301,6 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
 
        for (i = 0; i < 123; i++) {
                if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
-
                        /* workaround for gcc bug #37014 */
                        volatile int tmp_v = abs(cur_vit_mask - bin);
 
@@ -466,6 +405,78 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
        REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
 }
 
+/**
+ * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For non single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+{
+       int bb_spur = AR_NO_SPUR;
+       int bin;
+       int spur_freq_sd;
+       int spur_delta_phase;
+       int denominator;
+       int tmp, new;
+       int i;
+
+       int8_t mask_m[123];
+       int8_t mask_p[123];
+       int cur_bb_spur;
+       bool is2GHz = IS_CHAN_2GHZ(chan);
+
+       memset(&mask_m, 0, sizeof(int8_t) * 123);
+       memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+               if (AR_NO_SPUR == cur_bb_spur)
+                       break;
+               cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+               if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+                       bb_spur = cur_bb_spur;
+                       break;
+               }
+       }
+
+       if (AR_NO_SPUR == bb_spur)
+               return;
+
+       bin = bb_spur * 32;
+
+       tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+       new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+                    AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+                    AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+                    AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+       REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
+
+       new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+              AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+              AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+              AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+              SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+       REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+
+       spur_delta_phase = ((bb_spur * 524288) / 100) &
+               AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+       denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+       spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+       new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+              SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+              SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+       REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+       ar5008_hw_cmn_spur_mitigate(ah, chan, bin);
+}
+
 /**
  * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming
  * @ah: atheros hardware structure
index fc08162b58200143d5324e9825cab8384b6b5118..db6624527d9959d3ffd10a32f3fa76cb0b6dff83 100644 (file)
@@ -169,29 +169,17 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
 {
        int bb_spur = AR_NO_SPUR;
        int freq;
-       int bin, cur_bin;
+       int bin;
        int bb_spur_off, spur_subchannel_sd;
        int spur_freq_sd;
        int spur_delta_phase;
        int denominator;
-       int upper, lower, cur_vit_mask;
        int tmp, newVal;
        int i;
-       static const int pilot_mask_reg[4] = {
-               AR_PHY_TIMING7, AR_PHY_TIMING8,
-               AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
-       };
-       static const int chan_mask_reg[4] = {
-               AR_PHY_TIMING9, AR_PHY_TIMING10,
-               AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
-       };
-       static const int inc[4] = { 0, 100, 0, 0 };
        struct chan_centers centers;
 
        int8_t mask_m[123];
        int8_t mask_p[123];
-       int8_t mask_amt;
-       int tmp_mask;
        int cur_bb_spur;
        bool is2GHz = IS_CHAN_2GHZ(chan);
 
@@ -288,135 +276,7 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
        newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
        REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
 
-       cur_bin = -6000;
-       upper = bin + 100;
-       lower = bin - 100;
-
-       for (i = 0; i < 4; i++) {
-               int pilot_mask = 0;
-               int chan_mask = 0;
-               int bp = 0;
-               for (bp = 0; bp < 30; bp++) {
-                       if ((cur_bin > lower) && (cur_bin < upper)) {
-                               pilot_mask = pilot_mask | 0x1 << bp;
-                               chan_mask = chan_mask | 0x1 << bp;
-                       }
-                       cur_bin += 100;
-               }
-               cur_bin += inc[i];
-               REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
-               REG_WRITE(ah, chan_mask_reg[i], chan_mask);
-       }
-
-       cur_vit_mask = 6100;
-       upper = bin + 120;
-       lower = bin - 120;
-
-       for (i = 0; i < 123; i++) {
-               if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
-
-                       /* workaround for gcc bug #37014 */
-                       volatile int tmp_v = abs(cur_vit_mask - bin);
-
-                       if (tmp_v < 75)
-                               mask_amt = 1;
-                       else
-                               mask_amt = 0;
-                       if (cur_vit_mask < 0)
-                               mask_m[abs(cur_vit_mask / 100)] = mask_amt;
-                       else
-                               mask_p[cur_vit_mask / 100] = mask_amt;
-               }
-               cur_vit_mask -= 100;
-       }
-
-       tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
-               | (mask_m[48] << 26) | (mask_m[49] << 24)
-               | (mask_m[50] << 22) | (mask_m[51] << 20)
-               | (mask_m[52] << 18) | (mask_m[53] << 16)
-               | (mask_m[54] << 14) | (mask_m[55] << 12)
-               | (mask_m[56] << 10) | (mask_m[57] << 8)
-               | (mask_m[58] << 6) | (mask_m[59] << 4)
-               | (mask_m[60] << 2) | (mask_m[61] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
-       REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
-
-       tmp_mask = (mask_m[31] << 28)
-               | (mask_m[32] << 26) | (mask_m[33] << 24)
-               | (mask_m[34] << 22) | (mask_m[35] << 20)
-               | (mask_m[36] << 18) | (mask_m[37] << 16)
-               | (mask_m[48] << 14) | (mask_m[39] << 12)
-               | (mask_m[40] << 10) | (mask_m[41] << 8)
-               | (mask_m[42] << 6) | (mask_m[43] << 4)
-               | (mask_m[44] << 2) | (mask_m[45] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
-
-       tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
-               | (mask_m[18] << 26) | (mask_m[18] << 24)
-               | (mask_m[20] << 22) | (mask_m[20] << 20)
-               | (mask_m[22] << 18) | (mask_m[22] << 16)
-               | (mask_m[24] << 14) | (mask_m[24] << 12)
-               | (mask_m[25] << 10) | (mask_m[26] << 8)
-               | (mask_m[27] << 6) | (mask_m[28] << 4)
-               | (mask_m[29] << 2) | (mask_m[30] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
-
-       tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
-               | (mask_m[2] << 26) | (mask_m[3] << 24)
-               | (mask_m[4] << 22) | (mask_m[5] << 20)
-               | (mask_m[6] << 18) | (mask_m[7] << 16)
-               | (mask_m[8] << 14) | (mask_m[9] << 12)
-               | (mask_m[10] << 10) | (mask_m[11] << 8)
-               | (mask_m[12] << 6) | (mask_m[13] << 4)
-               | (mask_m[14] << 2) | (mask_m[15] << 0);
-       REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
-
-       tmp_mask = (mask_p[15] << 28)
-               | (mask_p[14] << 26) | (mask_p[13] << 24)
-               | (mask_p[12] << 22) | (mask_p[11] << 20)
-               | (mask_p[10] << 18) | (mask_p[9] << 16)
-               | (mask_p[8] << 14) | (mask_p[7] << 12)
-               | (mask_p[6] << 10) | (mask_p[5] << 8)
-               | (mask_p[4] << 6) | (mask_p[3] << 4)
-               | (mask_p[2] << 2) | (mask_p[1] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
-
-       tmp_mask = (mask_p[30] << 28)
-               | (mask_p[29] << 26) | (mask_p[28] << 24)
-               | (mask_p[27] << 22) | (mask_p[26] << 20)
-               | (mask_p[25] << 18) | (mask_p[24] << 16)
-               | (mask_p[23] << 14) | (mask_p[22] << 12)
-               | (mask_p[21] << 10) | (mask_p[20] << 8)
-               | (mask_p[19] << 6) | (mask_p[18] << 4)
-               | (mask_p[17] << 2) | (mask_p[16] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
-
-       tmp_mask = (mask_p[45] << 28)
-               | (mask_p[44] << 26) | (mask_p[43] << 24)
-               | (mask_p[42] << 22) | (mask_p[41] << 20)
-               | (mask_p[40] << 18) | (mask_p[39] << 16)
-               | (mask_p[38] << 14) | (mask_p[37] << 12)
-               | (mask_p[36] << 10) | (mask_p[35] << 8)
-               | (mask_p[34] << 6) | (mask_p[33] << 4)
-               | (mask_p[32] << 2) | (mask_p[31] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
-
-       tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
-               | (mask_p[59] << 26) | (mask_p[58] << 24)
-               | (mask_p[57] << 22) | (mask_p[56] << 20)
-               | (mask_p[55] << 18) | (mask_p[54] << 16)
-               | (mask_p[53] << 14) | (mask_p[52] << 12)
-               | (mask_p[51] << 10) | (mask_p[50] << 8)
-               | (mask_p[49] << 6) | (mask_p[48] << 4)
-               | (mask_p[47] << 2) | (mask_p[46] << 0);
-       REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
-       REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+       ar5008_hw_cmn_spur_mitigate(ah, chan, bin);
 
        REGWRITE_BUFFER_FLUSH(ah);
 }
index e82a0d4ce23f99247ea540be2a00dd4c26f9bd90..5dbc617ecf8a824eb61e5cf8d0bd231717f72a3f 100644 (file)
@@ -440,9 +440,9 @@ static inline void ath9k_htc_stop_btcoex(struct ath9k_htc_priv *priv)
 }
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
-#define OP_BT_PRIORITY_DETECTED    BIT(3)
-#define OP_BT_SCAN                 BIT(4)
-#define OP_TSF_RESET               BIT(6)
+#define OP_BT_PRIORITY_DETECTED    3
+#define OP_BT_SCAN                 4
+#define OP_TSF_RESET               6
 
 enum htc_op_flags {
        HTC_FWFLAG_NO_RMW,
index c1d2d0340febadb445bed891754f0565025f8f09..e8454db17634b95450f643ada6f52db82a57aa84 100644 (file)
@@ -1119,6 +1119,8 @@ bool ar9003_is_paprd_enabled(struct ath_hw *ah);
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
                                 struct ath9k_channel *chan);
+void ar5008_hw_cmn_spur_mitigate(struct ath_hw *ah,
+                                struct ath9k_channel *chan, int bin);
 void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array,
                                 struct ath9k_channel *chan, int ht40_delta);
 
index c9f93310c0d6c0abaffc780fd4c30b970a420c54..76842e6ca38e64c516c29a44699442b5987864c6 100644 (file)
@@ -651,6 +651,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
        unsigned int plen, void *payload, unsigned int outlen, void *out)
 {
        int err = -ENOMEM;
+       unsigned long time_left;
 
        if (!IS_ACCEPTING_CMD(ar))
                return -EIO;
@@ -672,8 +673,8 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
        err = __carl9170_exec_cmd(ar, &ar->cmd, false);
 
        if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) {
-               err = wait_for_completion_timeout(&ar->cmd_wait, HZ);
-               if (err == 0) {
+               time_left = wait_for_completion_timeout(&ar->cmd_wait, HZ);
+               if (time_left == 0) {
                        err = -ETIMEDOUT;
                        goto err_unbuf;
                }
index caa717bf52f3534c289949bd313b9497f21a630c..050506f842e9a63298920af2f5b8700e80aaf87b 100644 (file)
@@ -12,6 +12,7 @@ wil6210-y += debug.o
 wil6210-y += rx_reorder.o
 wil6210-y += ioctl.o
 wil6210-y += fw.o
+wil6210-y += pmc.o
 wil6210-$(CONFIG_WIL6210_TRACING) += trace.o
 wil6210-y += wil_platform.o
 wil6210-y += ethtool.o
index b97172667bc7b3c5c3ea3463c9b6573811a6d064..dbfcdd16628a25ddb4238d51988c9c5759fdf6b9 100644 (file)
@@ -402,11 +402,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        rsn_eid = sme->ie ?
                        cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
                        NULL;
-
-       if (sme->privacy && !rsn_eid) {
-               wil_err(wil, "Missing RSN IE for secure connection\n");
-               return -EINVAL;
-       }
+       if (sme->privacy && !rsn_eid)
+               wil_info(wil, "WSC connection\n");
 
        bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
                               sme->ssid, sme->ssid_len,
@@ -425,10 +422,17 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        wil->privacy = sme->privacy;
 
        if (wil->privacy) {
-               /* For secure assoc, send WMI_DELETE_CIPHER_KEY_CMD */
-               rc = wmi_del_cipher_key(wil, 0, bss->bssid);
+               /* For secure assoc, remove old keys */
+               rc = wmi_del_cipher_key(wil, 0, bss->bssid,
+                                       WMI_KEY_USE_PAIRWISE);
                if (rc) {
-                       wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n");
+                       wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
+                       goto out;
+               }
+               rc = wmi_del_cipher_key(wil, 0, bss->bssid,
+                                       WMI_KEY_USE_RX_GROUP);
+               if (rc) {
+                       wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
                        goto out;
                }
        }
@@ -458,11 +462,18 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
                goto out;
        }
        if (wil->privacy) {
-               conn.dot11_auth_mode = WMI_AUTH11_SHARED;
-               conn.auth_mode = WMI_AUTH_WPA2_PSK;
-               conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
-               conn.pairwise_crypto_len = 16;
-       } else {
+               if (rsn_eid) { /* regular secure connection */
+                       conn.dot11_auth_mode = WMI_AUTH11_SHARED;
+                       conn.auth_mode = WMI_AUTH_WPA2_PSK;
+                       conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
+                       conn.pairwise_crypto_len = 16;
+                       conn.group_crypto_type = WMI_CRYPT_AES_GCMP;
+                       conn.group_crypto_len = 16;
+               } else { /* WSC */
+                       conn.dot11_auth_mode = WMI_AUTH11_WSC;
+                       conn.auth_mode = WMI_AUTH_NONE;
+               }
+       } else { /* insecure connection */
                conn.dot11_auth_mode = WMI_AUTH11_OPEN;
                conn.auth_mode = WMI_AUTH_NONE;
        }
@@ -507,6 +518,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
        int rc;
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
+       wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code);
+
        rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
 
        return rc;
@@ -561,6 +574,39 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
        return 0;
 }
 
+static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
+                                              bool pairwise)
+{
+       struct wireless_dev *wdev = wil->wdev;
+       enum wmi_key_usage rc;
+       static const char * const key_usage_str[] = {
+               [WMI_KEY_USE_PAIRWISE]  = "WMI_KEY_USE_PAIRWISE",
+               [WMI_KEY_USE_RX_GROUP]  = "WMI_KEY_USE_RX_GROUP",
+               [WMI_KEY_USE_TX_GROUP]  = "WMI_KEY_USE_TX_GROUP",
+       };
+
+       if (pairwise) {
+               rc = WMI_KEY_USE_PAIRWISE;
+       } else {
+               switch (wdev->iftype) {
+               case NL80211_IFTYPE_STATION:
+                       rc = WMI_KEY_USE_RX_GROUP;
+                       break;
+               case NL80211_IFTYPE_AP:
+                       rc = WMI_KEY_USE_TX_GROUP;
+                       break;
+               default:
+                       /* TODO: Rx GTK or Tx GTK? */
+                       wil_err(wil, "Can't determine GTK type\n");
+                       rc = WMI_KEY_USE_RX_GROUP;
+                       break;
+               }
+       }
+       wil_dbg_misc(wil, "%s() -> %s\n", __func__, key_usage_str[rc]);
+
+       return rc;
+}
+
 static int wil_cfg80211_add_key(struct wiphy *wiphy,
                                struct net_device *ndev,
                                u8 key_index, bool pairwise,
@@ -568,13 +614,13 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
                                struct key_params *params)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
 
-       /* group key is not used */
-       if (!pairwise)
-               return 0;
+       wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
+                    pairwise ? "PTK" : "GTK");
 
-       return wmi_add_cipher_key(wil, key_index, mac_addr,
-                                 params->key_len, params->key);
+       return wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
+                                 params->key, key_usage);
 }
 
 static int wil_cfg80211_del_key(struct wiphy *wiphy,
@@ -583,12 +629,12 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
                                const u8 *mac_addr)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
 
-       /* group key is not used */
-       if (!pairwise)
-               return 0;
+       wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
+                    pairwise ? "PTK" : "GTK");
 
-       return wmi_del_cipher_key(wil, key_index, mac_addr);
+       return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
 }
 
 /* Need to be present or wiphy_new() will WARN */
@@ -661,11 +707,6 @@ static int wil_fix_bcon(struct wil6210_priv *wil,
        if (bcon->probe_resp_len <= hlen)
                return 0;
 
-       if (!bcon->proberesp_ies) {
-               bcon->proberesp_ies = f->u.probe_resp.variable;
-               bcon->proberesp_ies_len = bcon->probe_resp_len - hlen;
-               rc = 1;
-       }
        if (!bcon->assocresp_ies) {
                bcon->assocresp_ies = f->u.probe_resp.variable;
                bcon->assocresp_ies_len = bcon->probe_resp_len - hlen;
@@ -680,9 +721,19 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
                                      struct cfg80211_beacon_data *bcon)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp;
+       size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+       const u8 *pr_ies = NULL;
+       size_t pr_ies_len = 0;
        int rc;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
+       wil_print_bcon_data(bcon);
+
+       if (bcon->probe_resp_len > hlen) {
+               pr_ies = f->u.probe_resp.variable;
+               pr_ies_len = bcon->probe_resp_len - hlen;
+       }
 
        if (wil_fix_bcon(wil, bcon)) {
                wil_dbg_misc(wil, "Fixed bcon\n");
@@ -695,9 +746,7 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
         * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
         * bcon->beacon_ies);
         */
-       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP,
-                       bcon->proberesp_ies_len,
-                       bcon->proberesp_ies);
+       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, pr_ies_len, pr_ies);
        if (rc) {
                wil_err(wil, "set_ie(PROBE_RESP) failed\n");
                return rc;
@@ -725,6 +774,10 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
        struct cfg80211_beacon_data *bcon = &info->beacon;
        struct cfg80211_crypto_settings *crypto = &info->crypto;
        u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+       struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp;
+       size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+       const u8 *pr_ies = NULL;
+       size_t pr_ies_len = 0;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
 
@@ -744,6 +797,11 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
        wil_print_bcon_data(bcon);
        wil_print_crypto(wil, crypto);
 
+       if (bcon->probe_resp_len > hlen) {
+               pr_ies = f->u.probe_resp.variable;
+               pr_ies_len = bcon->probe_resp_len - hlen;
+       }
+
        if (wil_fix_bcon(wil, bcon)) {
                wil_dbg_misc(wil, "Fixed bcon\n");
                wil_print_bcon_data(bcon);
@@ -771,8 +829,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
         * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
         * bcon->beacon_ies);
         */
-       wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len,
-                  bcon->proberesp_ies);
+       wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, pr_ies_len, pr_ies);
        wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
                   bcon->assocresp_ies);
 
@@ -814,13 +871,9 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
        wmi_pcp_stop(wil);
 
        __wil_down(wil);
-       __wil_up(wil);
 
        mutex_unlock(&wil->mutex);
 
-       /* some functions above might fail (e.g. __wil_up). Nevertheless, we
-        * return success because AP has stopped
-        */
        return 0;
 }
 
@@ -830,6 +883,9 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy,
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
+       wil_dbg_misc(wil, "%s(%pM, reason=%d)\n", __func__, params->mac,
+                    params->reason_code);
+
        mutex_lock(&wil->mutex);
        wil6210_disconnect(wil, params->mac, params->reason_code, false);
        mutex_unlock(&wil->mutex);
index bbc22d88f78f27dadd73ea64134f5484ca9df497..8f9c0722a8018b605242a26307015a69ad3e48ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, 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
@@ -24,6 +24,7 @@
 #include "wil6210.h"
 #include "wmi.h"
 #include "txrx.h"
+#include "pmc.h"
 
 /* Nasty hack. Better have per device instances */
 static u32 mem_addr;
@@ -123,15 +124,17 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
 
                        if (cid < WIL6210_MAX_CID)
                                seq_printf(s,
-                                          "\n%pM CID %d TID %d BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",
+                                          "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",
                                           wil->sta[cid].addr, cid, tid,
+                                          txdata->dot1x_open ? "+" : "-",
                                           txdata->agg_wsize,
                                           txdata->agg_timeout,
                                           txdata->agg_amsdu ? "+" : "-",
                                           used, avail, sidle);
                        else
                                seq_printf(s,
-                                          "\nBroadcast [%3d|%3d] idle %s\n",
+                                          "\nBroadcast 1x%s [%3d|%3d] idle %s\n",
+                                          txdata->dot1x_open ? "+" : "-",
                                           used, avail, sidle);
 
                        wil_print_vring(s, wil, name, vring, '_', 'H');
@@ -702,6 +705,89 @@ static const struct file_operations fops_back = {
        .open  = simple_open,
 };
 
+/* pmc control, write:
+ * - "alloc <num descriptors> <descriptor_size>" to allocate PMC
+ * - "free" to release memory allocated for PMC
+ */
+static ssize_t wil_write_pmccfg(struct file *file, const char __user *buf,
+                               size_t len, loff_t *ppos)
+{
+       struct wil6210_priv *wil = file->private_data;
+       int rc;
+       char *kbuf = kmalloc(len + 1, GFP_KERNEL);
+       char cmd[9];
+       int num_descs, desc_size;
+
+       if (!kbuf)
+               return -ENOMEM;
+
+       rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
+       if (rc != len) {
+               kfree(kbuf);
+               return rc >= 0 ? -EIO : rc;
+       }
+
+       kbuf[len] = '\0';
+       rc = sscanf(kbuf, "%8s %d %d", cmd, &num_descs, &desc_size);
+       kfree(kbuf);
+
+       if (rc < 0)
+               return rc;
+
+       if (rc < 1) {
+               wil_err(wil, "pmccfg: no params given\n");
+               return -EINVAL;
+       }
+
+       if (0 == strcmp(cmd, "alloc")) {
+               if (rc != 3) {
+                       wil_err(wil, "pmccfg: alloc requires 2 params\n");
+                       return -EINVAL;
+               }
+               wil_pmc_alloc(wil, num_descs, desc_size);
+       } else if (0 == strcmp(cmd, "free")) {
+               if (rc != 1) {
+                       wil_err(wil, "pmccfg: free does not have any params\n");
+                       return -EINVAL;
+               }
+               wil_pmc_free(wil, true);
+       } else {
+               wil_err(wil, "pmccfg: Unrecognized command \"%s\"\n", cmd);
+               return -EINVAL;
+       }
+
+       return len;
+}
+
+static ssize_t wil_read_pmccfg(struct file *file, char __user *user_buf,
+                              size_t count, loff_t *ppos)
+{
+       struct wil6210_priv *wil = file->private_data;
+       char text[256];
+       char help[] = "pmc control, write:\n"
+       " - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n"
+       " - \"free\" to free memory allocated for pmc\n";
+
+       sprintf(text, "Last command status: %d\n\n%s",
+               wil_pmc_last_cmd_status(wil),
+               help);
+
+       return simple_read_from_buffer(user_buf, count, ppos, text,
+                                      strlen(text) + 1);
+}
+
+static const struct file_operations fops_pmccfg = {
+       .read = wil_read_pmccfg,
+       .write = wil_write_pmccfg,
+       .open  = simple_open,
+};
+
+static const struct file_operations fops_pmcdata = {
+       .open           = simple_open,
+       .read           = wil_pmc_read,
+       .llseek         = wil_pmc_llseek,
+};
+
 /*---tx_mgmt---*/
 /* Write mgmt frame to this file to send it */
 static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
@@ -1111,8 +1197,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)
                        status = "connected";
                        break;
                }
-               seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
-                          (p->data_port_open ? " data_port_open" : ""));
+               seq_printf(s, "[%d] %pM %s\n", i, p->addr, status);
 
                if (p->status == wil_sta_connected) {
                        rc = wil_cid_fill_sinfo(wil, i, &sinfo);
@@ -1292,8 +1377,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
                        status = "connected";
                        break;
                }
-               seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
-                          (p->data_port_open ? " data_port_open" : ""));
+               seq_printf(s, "[%d] %pM %s\n", i, p->addr, status);
 
                if (p->status == wil_sta_connected) {
                        spin_lock_bh(&p->tid_rx_lock);
@@ -1363,6 +1447,8 @@ static const struct {
        {"tx_mgmt",               S_IWUSR,      &fops_txmgmt},
        {"wmi_send",              S_IWUSR,      &fops_wmi},
        {"back",        S_IRUGO | S_IWUSR,      &fops_back},
+       {"pmccfg",      S_IRUGO | S_IWUSR,      &fops_pmccfg},
+       {"pmcdata",     S_IRUGO,                &fops_pmcdata},
        {"temp",        S_IRUGO,                &fops_temp},
        {"freq",        S_IRUGO,                &fops_freq},
        {"link",        S_IRUGO,                &fops_link},
@@ -1440,6 +1526,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
        if (IS_ERR_OR_NULL(dbg))
                return -ENODEV;
 
+       wil_pmc_init(wil);
+
        wil6210_debugfs_init_files(wil, dbg);
        wil6210_debugfs_init_isr(wil, dbg);
        wil6210_debugfs_init_blobs(wil, dbg);
@@ -1459,4 +1547,9 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil)
 {
        debugfs_remove_recursive(wil->debug);
        wil->debug = NULL;
+
+       /* free pmc memory without sending command to fw, as it will
+        * be reset on the way down anyway
+        */
+       wil_pmc_free(wil, false);
 }
index 38b953e108a714d10b89b9cd61d1c2144376c191..6d704aee3afd0f083fdb8861c1aa22a07d45bcd0 100644 (file)
 #define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
 #define WAIT_FOR_DISCONNECT_INTERVAL_MS 10
 
+bool debug_fw; /* = false; */
+module_param(debug_fw, bool, S_IRUGO);
+MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
+
 bool no_fw_recovery;
 module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery");
@@ -146,7 +150,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
        wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
                     sta->status);
 
-       sta->data_port_open = false;
        if (sta->status != wil_sta_unused) {
                if (!from_event)
                        wmi_disconnect_sta(wil, sta->addr, reason_code);
@@ -373,9 +376,10 @@ int wil_bcast_init(struct wil6210_priv *wil)
        if (ri < 0)
                return ri;
 
+       wil->bcast_vring = ri;
        rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order);
-       if (rc == 0)
-               wil->bcast_vring = ri;
+       if (rc)
+               wil->bcast_vring = -1;
 
        return rc;
 }
@@ -547,7 +551,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil)
 static int wil_target_reset(struct wil6210_priv *wil)
 {
        int delay = 0;
-       u32 x;
+       u32 x, x1 = 0;
 
        wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
 
@@ -602,12 +606,16 @@ static int wil_target_reset(struct wil6210_priv *wil)
        do {
                msleep(RST_DELAY);
                x = R(RGF_USER_BL + offsetof(struct RGF_BL, ready));
+               if (x1 != x) {
+                       wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n", x1, x);
+                       x1 = x;
+               }
                if (delay++ > RST_COUNT) {
                        wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
                                x);
                        return -ETIME;
                }
-       } while (!(x & BIT_BL_READY));
+       } while (x != BIT_BL_READY);
 
        C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
 
@@ -686,6 +694,17 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        WARN_ON(!mutex_is_locked(&wil->mutex));
        WARN_ON(test_bit(wil_status_napi_en, wil->status));
 
+       if (debug_fw) {
+               static const u8 mac[ETH_ALEN] = {
+                       0x00, 0xde, 0xad, 0x12, 0x34, 0x56,
+               };
+               struct net_device *ndev = wil_to_ndev(wil);
+
+               ether_addr_copy(ndev->perm_addr, mac);
+               ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
+               return 0;
+       }
+
        cancel_work_sync(&wil->disconnect_worker);
        wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
        wil_bcast_fini(wil);
index f2f7ea29558e058f27d7f934ba36769db36306c2..6042f61b016c010568c3b9f5903cff8ff668f0eb 100644 (file)
@@ -24,6 +24,11 @@ static int wil_open(struct net_device *ndev)
 
        wil_dbg_misc(wil, "%s()\n", __func__);
 
+       if (debug_fw) {
+               wil_err(wil, "%s() while in debug_fw mode\n", __func__);
+               return -EINVAL;
+       }
+
        return wil_up(wil);
 }
 
index 109986114abfa10d6bd6083fa52fb29de2912fea..58c79166a6d11a5d676b857ccee5f55f0b71a415 100644 (file)
@@ -27,10 +27,6 @@ MODULE_PARM_DESC(use_msi,
                 " Use MSI interrupt: "
                 "0 - don't, 1 - (default) - single, or 3");
 
-static bool debug_fw; /* = false; */
-module_param(debug_fw, bool, S_IRUGO);
-MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug");
-
 static
 void wil_set_capabilities(struct wil6210_priv *wil)
 {
@@ -133,8 +129,6 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
        mutex_lock(&wil->mutex);
        rc = wil_reset(wil, false);
        mutex_unlock(&wil->mutex);
-       if (debug_fw)
-               rc = 0;
        if (rc)
                goto release_irq;
 
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
new file mode 100644 (file)
index 0000000..8a8cdc6
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2012-2015 Qualcomm Atheros, 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.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include "wmi.h"
+#include "wil6210.h"
+#include "txrx.h"
+#include "pmc.h"
+
+struct desc_alloc_info {
+       dma_addr_t pa;
+       void      *va;
+};
+
+static int wil_is_pmc_allocated(struct pmc_ctx *pmc)
+{
+       return !!pmc->pring_va;
+}
+
+void wil_pmc_init(struct wil6210_priv *wil)
+{
+       memset(&wil->pmc, 0, sizeof(struct pmc_ctx));
+       mutex_init(&wil->pmc.lock);
+}
+
+/**
+ * Allocate the physical ring (p-ring) and the required
+ * number of descriptors of required size.
+ * Initialize the descriptors as required by pmc dma.
+ * The descriptors' buffers dwords are initialized to hold
+ * dword's serial number in the lsw and reserved value
+ * PCM_DATA_INVALID_DW_VAL in the msw.
+ */
+void wil_pmc_alloc(struct wil6210_priv *wil,
+                  int num_descriptors,
+                  int descriptor_size)
+{
+       u32 i;
+       struct pmc_ctx *pmc = &wil->pmc;
+       struct device *dev = wil_to_dev(wil);
+       struct wmi_pmc_cmd pmc_cmd = {0};
+
+       mutex_lock(&pmc->lock);
+
+       if (wil_is_pmc_allocated(pmc)) {
+               /* sanity check */
+               wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__);
+               goto no_release_err;
+       }
+
+       pmc->num_descriptors = num_descriptors;
+       pmc->descriptor_size = descriptor_size;
+
+       wil_dbg_misc(wil, "%s: %d descriptors x %d bytes each\n",
+                    __func__, num_descriptors, descriptor_size);
+
+       /* allocate descriptors info list in pmc context*/
+       pmc->descriptors = kcalloc(num_descriptors,
+                                 sizeof(struct desc_alloc_info),
+                                 GFP_KERNEL);
+       if (!pmc->descriptors) {
+               wil_err(wil, "%s: ERROR allocating pmc skb list\n", __func__);
+               goto no_release_err;
+       }
+
+       wil_dbg_misc(wil,
+                    "%s: allocated descriptors info list %p\n",
+                    __func__, pmc->descriptors);
+
+       /* Allocate pring buffer and descriptors.
+        * vring->va should be aligned on its size rounded up to power of 2
+        * This is granted by the dma_alloc_coherent
+        */
+       pmc->pring_va = dma_alloc_coherent(dev,
+                       sizeof(struct vring_tx_desc) * num_descriptors,
+                       &pmc->pring_pa,
+                       GFP_KERNEL);
+
+       wil_dbg_misc(wil,
+                    "%s: allocated pring %p => %pad. %zd x %d = total %zd bytes\n",
+                    __func__,
+                    pmc->pring_va, &pmc->pring_pa,
+                    sizeof(struct vring_tx_desc),
+                    num_descriptors,
+                    sizeof(struct vring_tx_desc) * num_descriptors);
+
+       if (!pmc->pring_va) {
+               wil_err(wil, "%s: ERROR allocating pmc pring\n", __func__);
+               goto release_pmc_skb_list;
+       }
+
+       /* initially, all descriptors are SW owned
+        * For Tx, Rx, and PMC, ownership bit is at the same location, thus
+        * we can use any
+        */
+       for (i = 0; i < num_descriptors; i++) {
+               struct vring_tx_desc *_d = &pmc->pring_va[i];
+               struct vring_tx_desc dd, *d = &dd;
+               int j = 0;
+
+               pmc->descriptors[i].va = dma_alloc_coherent(dev,
+                       descriptor_size,
+                       &pmc->descriptors[i].pa,
+                       GFP_KERNEL);
+
+               if (unlikely(!pmc->descriptors[i].va)) {
+                       wil_err(wil,
+                               "%s: ERROR allocating pmc descriptor %d",
+                               __func__, i);
+                       goto release_pmc_skbs;
+               }
+
+               for (j = 0; j < descriptor_size / sizeof(u32); j++) {
+                       u32 *p = (u32 *)pmc->descriptors[i].va + j;
+                       *p = PCM_DATA_INVALID_DW_VAL | j;
+               }
+
+               /* configure dma descriptor */
+               d->dma.addr.addr_low =
+                       cpu_to_le32(lower_32_bits(pmc->descriptors[i].pa));
+               d->dma.addr.addr_high =
+                       cpu_to_le16((u16)upper_32_bits(pmc->descriptors[i].pa));
+               d->dma.status = 0; /* 0 = HW_OWNED */
+               d->dma.length = cpu_to_le16(descriptor_size);
+               d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
+               *_d = *d;
+       }
+
+       wil_dbg_misc(wil, "%s: allocated successfully\n", __func__);
+
+       pmc_cmd.op = WMI_PMC_ALLOCATE;
+       pmc_cmd.ring_size = cpu_to_le16(pmc->num_descriptors);
+       pmc_cmd.mem_base = cpu_to_le64(pmc->pring_pa);
+
+       wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with ALLOCATE op\n", __func__);
+       pmc->last_cmd_status = wmi_send(wil,
+                                       WMI_PMC_CMDID,
+                                       &pmc_cmd,
+                                       sizeof(pmc_cmd));
+       if (pmc->last_cmd_status) {
+               wil_err(wil,
+                       "%s: WMI_PMC_CMD with ALLOCATE op failed with status %d",
+                       __func__, pmc->last_cmd_status);
+               goto release_pmc_skbs;
+       }
+
+       mutex_unlock(&pmc->lock);
+
+       return;
+
+release_pmc_skbs:
+       wil_err(wil, "%s: exit on error: Releasing skbs...\n", __func__);
+       for (i = 0; pmc->descriptors[i].va && i < num_descriptors; i++) {
+               dma_free_coherent(dev,
+                                 descriptor_size,
+                                 pmc->descriptors[i].va,
+                                 pmc->descriptors[i].pa);
+
+               pmc->descriptors[i].va = NULL;
+       }
+       wil_err(wil, "%s: exit on error: Releasing pring...\n", __func__);
+
+       dma_free_coherent(dev,
+                         sizeof(struct vring_tx_desc) * num_descriptors,
+                         pmc->pring_va,
+                         pmc->pring_pa);
+
+       pmc->pring_va = NULL;
+
+release_pmc_skb_list:
+       wil_err(wil, "%s: exit on error: Releasing descriptors info list...\n",
+               __func__);
+       kfree(pmc->descriptors);
+       pmc->descriptors = NULL;
+
+no_release_err:
+       pmc->last_cmd_status = -ENOMEM;
+       mutex_unlock(&pmc->lock);
+}
+
+/**
+ * Traverse the p-ring and release all buffers.
+ * At the end release the p-ring memory
+ */
+void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
+{
+       struct pmc_ctx *pmc = &wil->pmc;
+       struct device *dev = wil_to_dev(wil);
+       struct wmi_pmc_cmd pmc_cmd = {0};
+
+       mutex_lock(&pmc->lock);
+
+       pmc->last_cmd_status = 0;
+
+       if (!wil_is_pmc_allocated(pmc)) {
+               wil_dbg_misc(wil, "%s: Error, can't free - not allocated\n",
+                            __func__);
+               pmc->last_cmd_status = -EPERM;
+               mutex_unlock(&pmc->lock);
+               return;
+       }
+
+       if (send_pmc_cmd) {
+               wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with RELEASE op\n",
+                            __func__);
+               pmc_cmd.op = WMI_PMC_RELEASE;
+               pmc->last_cmd_status =
+                               wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd,
+                                        sizeof(pmc_cmd));
+               if (pmc->last_cmd_status) {
+                       wil_err(wil,
+                               "%s WMI_PMC_CMD with RELEASE op failed, status %d",
+                               __func__, pmc->last_cmd_status);
+                       /* There's nothing we can do with this error.
+                        * Normally, it should never occur.
+                        * Continue to freeing all memory allocated for pmc.
+                        */
+               }
+       }
+
+       if (pmc->pring_va) {
+               size_t buf_size = sizeof(struct vring_tx_desc) *
+                                 pmc->num_descriptors;
+
+               wil_dbg_misc(wil, "%s: free pring va %p\n",
+                            __func__, pmc->pring_va);
+               dma_free_coherent(dev, buf_size, pmc->pring_va, pmc->pring_pa);
+
+               pmc->pring_va = NULL;
+       } else {
+               pmc->last_cmd_status = -ENOENT;
+       }
+
+       if (pmc->descriptors) {
+               int i;
+
+               for (i = 0;
+                    pmc->descriptors[i].va && i < pmc->num_descriptors; i++) {
+                       dma_free_coherent(dev,
+                                         pmc->descriptor_size,
+                                         pmc->descriptors[i].va,
+                                         pmc->descriptors[i].pa);
+                       pmc->descriptors[i].va = NULL;
+               }
+               wil_dbg_misc(wil, "%s: free descriptor info %d/%d\n",
+                            __func__, i, pmc->num_descriptors);
+               wil_dbg_misc(wil,
+                            "%s: free pmc descriptors info list %p\n",
+                            __func__, pmc->descriptors);
+               kfree(pmc->descriptors);
+               pmc->descriptors = NULL;
+       } else {
+               pmc->last_cmd_status = -ENOENT;
+       }
+
+       mutex_unlock(&pmc->lock);
+}
+
+/**
+ * Status of the last operation requested via debugfs: alloc/free/read.
+ * 0 - success or negative errno
+ */
+int wil_pmc_last_cmd_status(struct wil6210_priv *wil)
+{
+       wil_dbg_misc(wil, "%s: status %d\n", __func__,
+                    wil->pmc.last_cmd_status);
+
+       return wil->pmc.last_cmd_status;
+}
+
+/**
+ * Read from required position up to the end of current descriptor,
+ * depends on descriptor size configured during alloc request.
+ */
+ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
+                    loff_t *f_pos)
+{
+       struct wil6210_priv *wil = filp->private_data;
+       struct pmc_ctx *pmc = &wil->pmc;
+       size_t retval = 0;
+       unsigned long long idx;
+       loff_t offset;
+       size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+
+       mutex_lock(&pmc->lock);
+
+       if (!wil_is_pmc_allocated(pmc)) {
+               wil_err(wil, "%s: error, pmc is not allocated!\n", __func__);
+               pmc->last_cmd_status = -EPERM;
+               mutex_unlock(&pmc->lock);
+               return -EPERM;
+       }
+
+       wil_dbg_misc(wil,
+                    "%s: size %u, pos %lld\n",
+                    __func__, (unsigned)count, *f_pos);
+
+       pmc->last_cmd_status = 0;
+
+       idx = *f_pos;
+       do_div(idx, pmc->descriptor_size);
+       offset = *f_pos - (idx * pmc->descriptor_size);
+
+       if (*f_pos >= pmc_size) {
+               wil_dbg_misc(wil, "%s: reached end of pmc buf: %lld >= %u\n",
+                            __func__, *f_pos, (unsigned)pmc_size);
+               pmc->last_cmd_status = -ERANGE;
+               goto out;
+       }
+
+       wil_dbg_misc(wil,
+                    "%s: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n",
+                    __func__, *f_pos, idx, offset, count);
+
+       /* if no errors, return the copied byte count */
+       retval = simple_read_from_buffer(buf,
+                                        count,
+                                        &offset,
+                                        pmc->descriptors[idx].va,
+                                        pmc->descriptor_size);
+       *f_pos += retval;
+out:
+       mutex_unlock(&pmc->lock);
+
+       return retval;
+}
+
+loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
+{
+       loff_t newpos;
+       struct wil6210_priv *wil = filp->private_data;
+       struct pmc_ctx *pmc = &wil->pmc;
+       size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+
+       switch (whence) {
+       case 0: /* SEEK_SET */
+               newpos = off;
+               break;
+
+       case 1: /* SEEK_CUR */
+               newpos = filp->f_pos + off;
+               break;
+
+       case 2: /* SEEK_END */
+               newpos = pmc_size;
+               break;
+
+       default: /* can't happen */
+               return -EINVAL;
+       }
+
+       if (newpos < 0)
+               return -EINVAL;
+       if (newpos > pmc_size)
+               newpos = pmc_size;
+
+       filp->f_pos = newpos;
+
+       return newpos;
+}
diff --git a/drivers/net/wireless/ath/wil6210/pmc.h b/drivers/net/wireless/ath/wil6210/pmc.h
new file mode 100644 (file)
index 0000000..bebc8d5
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012-2015 Qualcomm Atheros, 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.
+ */
+
+#include <linux/types.h>
+
+#define PCM_DATA_INVALID_DW_VAL (0xB0BA0000)
+
+void wil_pmc_init(struct wil6210_priv *wil);
+void wil_pmc_alloc(struct wil6210_priv *wil,
+                  int num_descriptors, int descriptor_size);
+void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd);
+int wil_pmc_last_cmd_status(struct wil6210_priv *wil);
+ssize_t wil_pmc_read(struct file *, char __user *, size_t, loff_t *);
+loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence);
index e8bd512d81a9b7bbd70b7d56e65e0133e39881b0..0113dac3a9a9f33b6190609e26057777a35aa8ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, 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
@@ -236,7 +236,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
                return -ENOMEM;
        }
 
-       d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
+       d->dma.d0 = RX_DMA_D0_CMD_DMA_RT | RX_DMA_D0_CMD_DMA_IT;
        wil_desc_addr_set(&d->dma.addr, pa);
        /* ip_length don't care */
        /* b11 don't care */
@@ -724,6 +724,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 
        cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
 
+       if (!wil->privacy)
+               txdata->dot1x_open = true;
        rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
                      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
        if (rc)
@@ -738,11 +740,13 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
        vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
 
        txdata->enabled = 1;
-       if (wil->sta[cid].data_port_open && (agg_wsize >= 0))
+       if (txdata->dot1x_open && (agg_wsize >= 0))
                wil_addba_tx_request(wil, id, agg_wsize);
 
        return 0;
  out_free:
+       txdata->dot1x_open = false;
+       txdata->enabled = 0;
        wil_vring_free(wil, vring, 1);
  out:
 
@@ -792,6 +796,8 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
 
        cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
 
+       if (!wil->privacy)
+               txdata->dot1x_open = true;
        rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd),
                      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
        if (rc)
@@ -809,6 +815,8 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
 
        return 0;
  out_free:
+       txdata->enabled = 0;
+       txdata->dot1x_open = false;
        wil_vring_free(wil, vring, 1);
  out:
 
@@ -828,6 +836,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
        wil_dbg_misc(wil, "%s() id=%d\n", __func__, id);
 
        spin_lock_bh(&txdata->lock);
+       txdata->dot1x_open = false;
        txdata->enabled = 0; /* no Tx can be in progress or start anew */
        spin_unlock_bh(&txdata->lock);
        /* make sure NAPI won't touch this vring */
@@ -848,12 +857,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
        if (cid < 0)
                return NULL;
 
-       if (!wil->sta[cid].data_port_open &&
-           (skb->protocol != cpu_to_be16(ETH_P_PAE)))
-               return NULL;
-
        /* TODO: fix for multiple TID */
        for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
+               if (!wil->vring_tx_data[i].dot1x_open &&
+                   (skb->protocol != cpu_to_be16(ETH_P_PAE)))
+                       continue;
                if (wil->vring2cid_tid[i][0] == cid) {
                        struct vring *v = &wil->vring_tx[i];
 
@@ -883,7 +891,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
 
        /* In the STA mode, it is expected to have only 1 VRING
         * for the AP we connected to.
-        * find 1-st vring and see whether it is eligible for data
+        * find 1-st vring eligible for this skb and use it.
         */
        for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
                v = &wil->vring_tx[i];
@@ -894,9 +902,9 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
                if (cid >= WIL6210_MAX_CID) /* skip BCAST */
                        continue;
 
-               if (!wil->sta[cid].data_port_open &&
+               if (!wil->vring_tx_data[i].dot1x_open &&
                    (skb->protocol != cpu_to_be16(ETH_P_PAE)))
-                       break;
+                       continue;
 
                wil_dbg_txrx(wil, "Tx -> ring %d\n", i);
 
@@ -918,7 +926,6 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
  *    in all cases override dest address to unicast peer's address
  * Use old strategy when new is not supported yet:
  *  - for PBSS
- *  - for secure link
  */
 static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
                                         struct sk_buff *skb)
@@ -931,6 +938,9 @@ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
        v = &wil->vring_tx[i];
        if (!v->va)
                return NULL;
+       if (!wil->vring_tx_data[i].dot1x_open &&
+           (skb->protocol != cpu_to_be16(ETH_P_PAE)))
+               return NULL;
 
        return v;
 }
@@ -963,7 +973,8 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
                cid = wil->vring2cid_tid[i][0];
                if (cid >= WIL6210_MAX_CID) /* skip BCAST */
                        continue;
-               if (!wil->sta[cid].data_port_open)
+               if (!wil->vring_tx_data[i].dot1x_open &&
+                   (skb->protocol != cpu_to_be16(ETH_P_PAE)))
                        continue;
 
                /* don't Tx back to source when re-routing Rx->Tx at the AP */
@@ -989,7 +1000,8 @@ found:
                cid = wil->vring2cid_tid[i][0];
                if (cid >= WIL6210_MAX_CID) /* skip BCAST */
                        continue;
-               if (!wil->sta[cid].data_port_open)
+               if (!wil->vring_tx_data[i].dot1x_open &&
+                   (skb->protocol != cpu_to_be16(ETH_P_PAE)))
                        continue;
 
                if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN))
@@ -1016,9 +1028,6 @@ static struct vring *wil_find_tx_bcast(struct wil6210_priv *wil,
        if (wdev->iftype != NL80211_IFTYPE_AP)
                return wil_find_tx_bcast_2(wil, skb);
 
-       if (wil->privacy)
-               return wil_find_tx_bcast_2(wil, skb);
-
        return wil_find_tx_bcast_1(wil, skb);
 }
 
@@ -1144,13 +1153,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
        wil_tx_desc_map(d, pa, len, vring_index);
        if (unlikely(mcast)) {
                d->mac.d[0] |= BIT(MAC_CFG_DESC_TX_0_MCS_EN_POS); /* MCS 0 */
-               if (unlikely(len > WIL_BCAST_MCS0_LIMIT)) {
-                       /* set MCS 1 */
+               if (unlikely(len > WIL_BCAST_MCS0_LIMIT)) /* set MCS 1 */
                        d->mac.d[0] |= (1 << MAC_CFG_DESC_TX_0_MCS_INDEX_POS);
-                       /* packet mode 2 */
-                       d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS) |
-                                      (2 << MAC_CFG_DESC_TX_1_PKT_MODE_POS);
-               }
        }
        /* Process TCP/UDP checksum offloading */
        if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) {
index d90c8aa20c157924cadde2ef8f1bdad9bcab16ae..0c4638487c742c3c5cbace887a95562a8e618ea2 100644 (file)
@@ -384,19 +384,27 @@ struct vring_rx_mac {
  *  [word 7] length
  */
 
-#define RX_DMA_D0_CMD_DMA_IT     BIT(10)
-
-/* Error field, offload bits */
-#define RX_DMA_ERROR_L3_ERR   BIT(4)
-#define RX_DMA_ERROR_L4_ERR   BIT(5)
+#define RX_DMA_D0_CMD_DMA_EOP  BIT(8)
+#define RX_DMA_D0_CMD_DMA_RT   BIT(9)  /* always 1 */
+#define RX_DMA_D0_CMD_DMA_IT   BIT(10) /* interrupt */
+
+/* Error field */
+#define RX_DMA_ERROR_FCS       BIT(0)
+#define RX_DMA_ERROR_MIC       BIT(1)
+#define RX_DMA_ERROR_KEY       BIT(2) /* Key missing */
+#define RX_DMA_ERROR_REPLAY    BIT(3)
+#define RX_DMA_ERROR_L3_ERR    BIT(4)
+#define RX_DMA_ERROR_L4_ERR    BIT(5)
 
 /* Status field */
-#define RX_DMA_STATUS_DU         BIT(0)
-#define RX_DMA_STATUS_ERROR      BIT(2)
-
+#define RX_DMA_STATUS_DU       BIT(0)
+#define RX_DMA_STATUS_EOP      BIT(1)
+#define RX_DMA_STATUS_ERROR    BIT(2)
+#define RX_DMA_STATUS_MI       BIT(3) /* MAC Interrupt is asserted */
 #define RX_DMA_STATUS_L3I      BIT(4)
 #define RX_DMA_STATUS_L4I      BIT(5)
 #define RX_DMA_STATUS_PHY_INFO BIT(6)
+#define RX_DMA_STATUS_FFM      BIT(7) /* EtherType Flex Filter Match */
 
 struct vring_rx_dma {
        u32 d0;
index 4310972c9e1687b5b12dc4c101c9076932d907a8..f3513a1fa4240d8b44504c987e07aa948c99953e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
 #include <linux/timex.h>
+#include <linux/types.h>
 #include "wil_platform.h"
 
 extern bool no_fw_recovery;
@@ -29,10 +30,11 @@ extern unsigned short rx_ring_overflow_thrsh;
 extern int agg_wsize;
 extern u32 vring_idle_trsh;
 extern bool rx_align_2;
+extern bool debug_fw;
 
 #define WIL_NAME "wil6210"
 #define WIL_FW_NAME "wil6210.fw" /* code */
-#define WIL_FW2_NAME "wil6210.board" /* board & radio parameters */
+#define WIL_FW2_NAME "wil6210.brd" /* board & radio parameters */
 
 #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
 
@@ -396,6 +398,7 @@ struct vring {
  * Additional data for Tx Vring
  */
 struct vring_tx_data {
+       bool dot1x_open;
        int enabled;
        cycles_t idle, last_idle, begin;
        u8 agg_wsize; /* agreed aggregation window, 0 - no agg */
@@ -484,7 +487,6 @@ struct wil_sta_info {
        u8 addr[ETH_ALEN];
        enum wil_sta_status status;
        struct wil_net_stats stats;
-       bool data_port_open; /* can send any data, not only EAPOL */
        /* Rx BACK */
        struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM];
        spinlock_t tid_rx_lock; /* guarding tid_rx array */
@@ -526,6 +528,17 @@ struct wil_probe_client_req {
        u8 cid;
 };
 
+struct pmc_ctx {
+       /* alloc, free, and read operations must own the lock */
+       struct mutex            lock;
+       struct vring_tx_desc    *pring_va;
+       dma_addr_t              pring_pa;
+       struct desc_alloc_info  *descriptors;
+       int                     last_cmd_status;
+       int                     num_descriptors;
+       int                     descriptor_size;
+};
+
 struct wil6210_priv {
        struct pci_dev *pdev;
        int n_msi;
@@ -610,6 +623,8 @@ struct wil6210_priv {
 
        void *platform_handle;
        struct wil_platform_ops platform_ops;
+
+       struct pmc_ctx pmc;
 };
 
 #define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -701,9 +716,10 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid);
 int wmi_set_channel(struct wil6210_priv *wil, int channel);
 int wmi_get_channel(struct wil6210_priv *wil, int *channel);
 int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
-                      const void *mac_addr);
+                      const void *mac_addr, int key_usage);
 int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
-                      const void *mac_addr, int key_len, const void *key);
+                      const void *mac_addr, int key_len, const void *key,
+                      int key_usage);
 int wmi_echo(struct wil6210_priv *wil);
 int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
index 9fe2085be2c5b86d77e9346f003c7f38656ff3d3..3dc8daf69bd2309bdcf9d0719e71bac6b707771d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, 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
@@ -543,55 +543,22 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
        }
 }
 
-static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid, u16 wsize)
+static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 {
-       struct vring_tx_data *t;
-       int i;
+       struct wmi_vring_en_event *evt = d;
+       u8 vri = evt->vring_index;
 
-       for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
-               if (cid != wil->vring2cid_tid[i][0])
-                       continue;
-               t = &wil->vring_tx_data[i];
-               if (!t->enabled)
-                       continue;
+       wil_dbg_wmi(wil, "Enable vring %d\n", vri);
 
-               wil_addba_tx_request(wil, i, wsize);
-       }
-}
-
-static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
-{
-       struct wmi_data_port_open_event *evt = d;
-       u8 cid = evt->cid;
-
-       wil_dbg_wmi(wil, "Link UP for CID %d\n", cid);
-
-       if (cid >= ARRAY_SIZE(wil->sta)) {
-               wil_err(wil, "Link UP for invalid CID %d\n", cid);
+       if (vri >= ARRAY_SIZE(wil->vring_tx)) {
+               wil_err(wil, "Enable for invalid vring %d\n", vri);
                return;
        }
-
-       wil->sta[cid].data_port_open = true;
-       if (agg_wsize >= 0)
-               wil_addba_tx_cid(wil, cid, agg_wsize);
-}
-
-static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len)
-{
-       struct net_device *ndev = wil_to_ndev(wil);
-       struct wmi_wbe_link_down_event *evt = d;
-       u8 cid = evt->cid;
-
-       wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n",
-                   cid, le32_to_cpu(evt->reason));
-
-       if (cid >= ARRAY_SIZE(wil->sta)) {
-               wil_err(wil, "Link DOWN for invalid CID %d\n", cid);
+       wil->vring_tx_data[vri].dot1x_open = true;
+       if (vri == wil->bcast_vring) /* no BA for bcast */
                return;
-       }
-
-       wil->sta[cid].data_port_open = false;
-       netif_carrier_off(ndev);
+       if (agg_wsize >= 0)
+               wil_addba_tx_request(wil, vri, agg_wsize);
 }
 
 static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
@@ -695,11 +662,10 @@ static const struct {
        {WMI_CONNECT_EVENTID,           wmi_evt_connect},
        {WMI_DISCONNECT_EVENTID,        wmi_evt_disconnect},
        {WMI_EAPOL_RX_EVENTID,          wmi_evt_eapol_rx},
-       {WMI_DATA_PORT_OPEN_EVENTID,    wmi_evt_linkup},
-       {WMI_WBE_LINKDOWN_EVENTID,      wmi_evt_linkdown},
        {WMI_BA_STATUS_EVENTID,         wmi_evt_ba_status},
        {WMI_RCP_ADDBA_REQ_EVENTID,     wmi_evt_addba_rx_req},
        {WMI_DELBA_EVENTID,             wmi_evt_delba},
+       {WMI_VRING_EN_EVENTID,          wmi_evt_vring_en},
 };
 
 /*
@@ -844,7 +810,7 @@ int wmi_echo(struct wil6210_priv *wil)
        };
 
        return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
-                        WMI_ECHO_RSP_EVENTID, NULL, 0, 20);
+                       WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
 }
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
@@ -985,7 +951,7 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel)
 }
 
 int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
-                      const void *mac_addr)
+                      const void *mac_addr, int key_usage)
 {
        struct wmi_delete_cipher_key_cmd cmd = {
                .key_index = key_index,
@@ -998,11 +964,12 @@ int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
 }
 
 int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
-                      const void *mac_addr, int key_len, const void *key)
+                      const void *mac_addr, int key_len, const void *key,
+                      int key_usage)
 {
        struct wmi_add_cipher_key_cmd cmd = {
                .key_index = key_index,
-               .key_usage = WMI_KEY_USE_PAIRWISE,
+               .key_usage = key_usage,
                .key_len = key_len,
        };
 
@@ -1238,7 +1205,8 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
                    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
 
        rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
-                     WMI_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), 100);
+                     WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
+                     100);
        if (rc)
                return rc;
 
index b2905531535039f6ae91835ee592a2960f140f83..cc04ab73b398c83c74675e0137b02b9818d61f63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
  * Copyright (c) 2006-2012 Wilocity .
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -253,8 +253,8 @@ struct wmi_set_passphrase_cmd {
  */
 enum wmi_key_usage {
        WMI_KEY_USE_PAIRWISE    = 0,
-       WMI_KEY_USE_GROUP       = 1,
-       WMI_KEY_USE_TX          = 2,  /* default Tx Key - Static WEP only */
+       WMI_KEY_USE_RX_GROUP    = 1,
+       WMI_KEY_USE_TX_GROUP    = 2,
 };
 
 struct wmi_add_cipher_key_cmd {
@@ -835,6 +835,21 @@ struct wmi_temp_sense_cmd {
        __le32 measure_mode;
 } __packed;
 
+/*
+ * WMI_PMC_CMDID
+ */
+enum wmi_pmc_op_e {
+       WMI_PMC_ALLOCATE = 0,
+       WMI_PMC_RELEASE = 1,
+};
+
+struct wmi_pmc_cmd {
+       u8 op;          /* enum wmi_pmc_cmd_op_type */
+       u8 reserved;
+       __le16 ring_size;
+       __le64 mem_base;
+} __packed;
+
 /*
  * WMI Events
  */
@@ -870,7 +885,7 @@ enum wmi_event_id {
        WMI_VRING_CFG_DONE_EVENTID              = 0x1821,
        WMI_BA_STATUS_EVENTID                   = 0x1823,
        WMI_RCP_ADDBA_REQ_EVENTID               = 0x1824,
-       WMI_ADDBA_RESP_SENT_EVENTID             = 0x1825,
+       WMI_RCP_ADDBA_RESP_SENT_EVENTID         = 0x1825,
        WMI_DELBA_EVENTID                       = 0x1826,
        WMI_GET_SSID_EVENTID                    = 0x1828,
        WMI_GET_PCP_CHANNEL_EVENTID             = 0x182a,
@@ -882,7 +897,7 @@ enum wmi_event_id {
        WMI_WRITE_MAC_TXQ_EVENTID               = 0x1833,
        WMI_WRITE_MAC_XQ_FIELD_EVENTID          = 0x1834,
 
-       WMI_BEAFORMING_MGMT_DONE_EVENTID        = 0x1836,
+       WMI_BEAMFORMING_MGMT_DONE_EVENTID       = 0x1836,
        WMI_BF_TXSS_MGMT_DONE_EVENTID           = 0x1837,
        WMI_BF_RXSS_MGMT_DONE_EVENTID           = 0x1839,
        WMI_RS_MGMT_DONE_EVENTID                = 0x1852,
@@ -894,11 +909,12 @@ enum wmi_event_id {
 
        /* Performance monitoring events */
        WMI_DATA_PORT_OPEN_EVENTID              = 0x1860,
-       WMI_WBE_LINKDOWN_EVENTID                = 0x1861,
+       WMI_WBE_LINK_DOWN_EVENTID               = 0x1861,
 
        WMI_BF_CTRL_DONE_EVENTID                = 0x1862,
        WMI_NOTIFY_REQ_DONE_EVENTID             = 0x1863,
        WMI_GET_STATUS_DONE_EVENTID             = 0x1864,
+       WMI_VRING_EN_EVENTID                    = 0x1865,
 
        WMI_UNIT_TEST_EVENTID                   = 0x1900,
        WMI_FLASH_READ_DONE_EVENTID             = 0x1902,
@@ -1147,7 +1163,7 @@ struct wmi_vring_cfg_done_event {
 } __packed;
 
 /*
- * WMI_ADDBA_RESP_SENT_EVENTID
+ * WMI_RCP_ADDBA_RESP_SENT_EVENTID
  */
 struct wmi_rcp_addba_resp_sent_event {
        u8 cidxtid;
@@ -1179,7 +1195,7 @@ struct wmi_cfg_rx_chain_done_event {
 } __packed;
 
 /*
- * WMI_WBE_LINKDOWN_EVENTID
+ * WMI_WBE_LINK_DOWN_EVENTID
  */
 enum wmi_wbe_link_down_event_reason {
        WMI_WBE_REASON_USER_REQUEST     = 0,
@@ -1201,6 +1217,14 @@ struct wmi_data_port_open_event {
        u8 reserved[3];
 } __packed;
 
+/*
+ * WMI_VRING_EN_EVENTID
+ */
+struct wmi_vring_en_event {
+       u8 vring_index;
+       u8 reserved[3];
+} __packed;
+
 /*
  * WMI_GET_PCP_CHANNEL_EVENTID
  */
index 8a69544485a93d7bf7ac87452fd2dffb407382ab..71779b9e4bbef3569a3543a5bcc69b4d4bb4cf76 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/acpi.h>
 #include <net/cfg80211.h>
 
 #include <defs.h>
@@ -1116,12 +1117,25 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
 static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
 
 
+static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
+                                                 int val)
+{
+#if IS_ENABLED(CONFIG_ACPI)
+       struct acpi_device *adev;
+
+       adev = ACPI_COMPANION(dev);
+       if (adev)
+               adev->flags.power_manageable = 0;
+#endif
+}
+
 static int brcmf_ops_sdio_probe(struct sdio_func *func,
                                const struct sdio_device_id *id)
 {
        int err;
        struct brcmf_sdio_dev *sdiodev;
        struct brcmf_bus *bus_if;
+       struct device *dev;
 
        brcmf_dbg(SDIO, "Enter\n");
        brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -1129,6 +1143,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
        brcmf_dbg(SDIO, "Function#: %d\n", func->num);
 
+       dev = &func->dev;
+       /* prohibit ACPI power management for this device */
+       brcmf_sdiod_acpi_set_power_manageable(dev, 0);
+
        /* Consume func num 1 but dont do anything with it. */
        if (func->num == 1)
                return 0;
index 77656c711bedbfc44a8a7ddf97b58cb3efabf24a..26c65872dae3b1b7184d377277a7fe86e125d5eb 100644 (file)
 #include "core.h"
 #include "commonring.h"
 
-
-/* dma flushing needs implementation for mips and arm platforms. Should
- * be put in util. Note, this is not real flushing. It is virtual non
- * cached memory. Only write buffers should have to be drained. Though
- * this may be different depending on platform......
- * SEE ALSO msgbuf.c
- */
-#define brcmf_dma_flush(addr, len)
-#define brcmf_dma_invalidate_cache(addr, len)
-
-
 void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
                                  int (*cr_ring_bell)(void *ctx),
                                  int (*cr_update_rptr)(void *ctx),
@@ -206,14 +195,9 @@ int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
        address = commonring->buf_addr;
        address += (commonring->f_ptr * commonring->item_len);
        if (commonring->f_ptr > commonring->w_ptr) {
-               brcmf_dma_flush(address,
-                               (commonring->depth - commonring->f_ptr) *
-                               commonring->item_len);
                address = commonring->buf_addr;
                commonring->f_ptr = 0;
        }
-       brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
-                       commonring->item_len);
 
        commonring->f_ptr = commonring->w_ptr;
 
@@ -258,8 +242,6 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
        if (commonring->r_ptr == commonring->depth)
                commonring->r_ptr = 0;
 
-       brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
-
        return ret_addr;
 }
 
index 8ff31ffa4a412ecb630baee5898a355df5ffb959..7ae6461df932b77bfe97e7add765c48de1e53616 100644 (file)
@@ -25,7 +25,7 @@
 
 #define BRCMF_FW_MAX_NVRAM_SIZE                        64000
 #define BRCMF_FW_NVRAM_DEVPATH_LEN             19      /* devpath0=pcie/1/4/ */
-#define BRCMF_FW_NVRAM_PCIEDEV_LEN             9       /* pcie/1/4/ */
+#define BRCMF_FW_NVRAM_PCIEDEV_LEN             10      /* pcie/1/4/ + \0 */
 
 char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
 module_param_string(firmware_path, brcmf_firmware_path,
@@ -66,6 +66,12 @@ struct nvram_parser {
        bool multi_dev_v2;
 };
 
+/**
+ * is_nvram_char() - check if char is a valid one for NVRAM entry
+ *
+ * It accepts all printable ASCII chars except for '#' which opens a comment.
+ * Please note that ' ' (space) while accepted is not a valid key name char.
+ */
 static bool is_nvram_char(char c)
 {
        /* comment marker excluded */
@@ -73,7 +79,7 @@ static bool is_nvram_char(char c)
                return false;
 
        /* key and value may have any other readable character */
-       return (c > 0x20 && c < 0x7f);
+       return (c >= 0x20 && c < 0x7f);
 }
 
 static bool is_whitespace(char c)
@@ -120,7 +126,7 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
                        nvp->multi_dev_v1 = true;
                if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
                        nvp->multi_dev_v2 = true;
-       } else if (!is_nvram_char(c)) {
+       } else if (!is_nvram_char(c) || c == ' ') {
                brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
                          nvp->line, nvp->column);
                return COMMENT;
@@ -162,17 +168,20 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
 static enum nvram_parser_state
 brcmf_nvram_handle_comment(struct nvram_parser *nvp)
 {
-       char *eol, *sol;
+       char *eoc, *sol;
 
        sol = (char *)&nvp->fwnv->data[nvp->pos];
-       eol = strchr(sol, '\n');
-       if (eol == NULL)
-               return END;
+       eoc = strchr(sol, '\n');
+       if (!eoc) {
+               eoc = strchr(sol, '\0');
+               if (!eoc)
+                       return END;
+       }
 
        /* eat all moving to next line */
        nvp->line++;
        nvp->column = 1;
-       nvp->pos += (eol - sol) + 1;
+       nvp->pos += (eoc - sol) + 1;
        return IDLE;
 }
 
@@ -222,6 +231,10 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
 static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
                                    u16 bus_nr)
 {
+       /* Device path with a leading '=' key-value separator */
+       char pcie_path[] = "=pcie/?/?";
+       size_t pcie_len;
+
        u32 i, j;
        bool found;
        u8 *nvram;
@@ -238,6 +251,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
        /* First search for the devpathX and see if it is the configuration
         * for domain_nr/bus_nr. Search complete nvp
         */
+       snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
+                bus_nr);
+       pcie_len = strlen(pcie_path);
        found = false;
        i = 0;
        while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
@@ -245,13 +261,10 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
                 * Y = domain_nr, Z = bus_nr, X = virtual ID
                 */
                if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
-                   (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) {
-                       if (((nvp->nvram[i + 14] - '0') == domain_nr) &&
-                           ((nvp->nvram[i + 16] - '0') == bus_nr)) {
-                               id = nvp->nvram[i + 7] - '0';
-                               found = true;
-                               break;
-                       }
+                   (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
+                       id = nvp->nvram[i + 7] - '0';
+                       found = true;
+                       break;
                }
                while (nvp->nvram[i] != 0)
                        i++;
@@ -297,6 +310,8 @@ fail:
 static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
                                    u16 bus_nr)
 {
+       char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
+       size_t len;
        u32 i, j;
        u8 *nvram;
 
@@ -308,14 +323,13 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
         * Valid entries are of type pcie/X/Y/ where X = domain_nr and
         * Y = bus_nr.
         */
+       snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
+       len = strlen(prefix);
        i = 0;
        j = 0;
-       while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) {
-               if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) &&
-                   (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') &&
-                   ((nvp->nvram[i + 5] - '0') == domain_nr) &&
-                   ((nvp->nvram[i + 7] - '0') == bus_nr)) {
-                       i += BRCMF_FW_NVRAM_PCIEDEV_LEN;
+       while (i < nvp->nvram_len - len) {
+               if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
+                       i += len;
                        while (nvp->nvram[i] != 0) {
                                nvram[j] = nvp->nvram[i];
                                i++;
index eb1325371d3a3aa9eba03e5ba83e65135f218f4e..59440631fec50637fc3f35e162defb230d1f420c 100644 (file)
@@ -249,8 +249,8 @@ void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
 }
 
 
-void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
-                           struct sk_buff *skb)
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+                          struct sk_buff *skb)
 {
        struct brcmf_flowring_ring *ring;
 
@@ -271,6 +271,7 @@ void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
                if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
                        brcmf_flowring_block(flow, flowid, false);
        }
+       return skb_queue_len(&ring->skblist);
 }
 
 
index a34cd394c616c0a11f861c06f18030d3c7129133..5551861a44bc427bca80d096f7809db6c2f12b42 100644 (file)
@@ -64,8 +64,8 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
 void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
 void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
 u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
-void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
-                           struct sk_buff *skb);
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+                          struct sk_buff *skb);
 struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
 void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
                             struct sk_buff *skb);
index f0dda0ecd23b4395219f31ef88475329e0ab69f2..5017eaa4af45fdd8f9dfd1034919c5042cce7cd8 100644 (file)
@@ -635,7 +635,7 @@ static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
        return 0;
 }
 
-static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
+static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
                                          u32 slot_id, struct sk_buff **pktout,
                                          bool remove_item)
 {
index 65efb146898844510aa489502ee2c9db23906c92..1b47de067d25cbb4b194ca8eae02986a3f196092 100644 (file)
@@ -73,7 +73,7 @@
 #define BRCMF_MSGBUF_TX_FLUSH_CNT1             32
 #define BRCMF_MSGBUF_TX_FLUSH_CNT2             96
 
-#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS       64
+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS       96
 #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS     32
 
 struct msgbuf_common_hdr {
@@ -278,16 +278,6 @@ struct brcmf_msgbuf_pktids {
        struct brcmf_msgbuf_pktid *array;
 };
 
-
-/* dma flushing needs implementation for mips and arm platforms. Should
- * be put in util. Note, this is not real flushing. It is virtual non
- * cached memory. Only write buffers should have to be drained. Though
- * this may be different depending on platform......
- */
-#define brcmf_dma_flush(addr, len)
-#define brcmf_dma_invalidate_cache(addr, len)
-
-
 static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
 
 
@@ -462,7 +452,6 @@ static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
                memcpy(msgbuf->ioctbuf, buf, buf_len);
        else
                memset(msgbuf->ioctbuf, 0, buf_len);
-       brcmf_dma_flush(ioctl_buf, buf_len);
 
        err = brcmf_commonring_write_complete(commonring);
        brcmf_commonring_unlock(commonring);
@@ -795,6 +784,8 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
        struct brcmf_flowring *flow = msgbuf->flow;
        struct ethhdr *eh = (struct ethhdr *)(skb->data);
        u32 flowid;
+       u32 queue_count;
+       bool force;
 
        flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
        if (flowid == BRCMF_FLOWRING_INVALID_ID) {
@@ -802,8 +793,9 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
                if (flowid == BRCMF_FLOWRING_INVALID_ID)
                        return -ENOMEM;
        }
-       brcmf_flowring_enqueue(flow, flowid, skb);
-       brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false);
+       queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
+       force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
+       brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);
 
        return 0;
 }
index c824570ddea3208b1f20230a6eecbc193dd68c50..03f35e0c52ca5469f49a7d43a39edac648563c10 100644 (file)
@@ -39,10 +39,16 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
        if (!sdiodev->pdata)
                return;
 
+       if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+               sdiodev->pdata->drive_strength = val;
+
+       /* make sure there are interrupts defined in the node */
+       if (!of_find_property(np, "interrupts", NULL))
+               return;
+
        irq = irq_of_parse_and_map(np, 0);
        if (!irq) {
                brcmf_err("interrupt could not be mapped\n");
-               devm_kfree(dev, sdiodev->pdata);
                return;
        }
        irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
@@ -50,7 +56,4 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
        sdiodev->pdata->oob_irq_supported = true;
        sdiodev->pdata->oob_irq_nr = irq;
        sdiodev->pdata->oob_irq_flags = irqf;
-
-       if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
-               sdiodev->pdata->drive_strength = val;
 }
index 79ca24e6d2c5a931b1ac54b6a117e18780bc942c..37a2624d7bbaed4a79fb3dcf2d6a23f725f3ea97 100644 (file)
@@ -112,10 +112,11 @@ enum brcmf_pcie_state {
                                                 BRCMF_PCIE_MB_INT_D2H3_DB0 | \
                                                 BRCMF_PCIE_MB_INT_D2H3_DB1)
 
-#define BRCMF_PCIE_MIN_SHARED_VERSION          4
+#define BRCMF_PCIE_MIN_SHARED_VERSION          5
 #define BRCMF_PCIE_MAX_SHARED_VERSION          5
 #define BRCMF_PCIE_SHARED_VERSION_MASK         0x00FF
-#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT       0x4000
+#define BRCMF_PCIE_SHARED_DMA_INDEX            0x10000
+#define BRCMF_PCIE_SHARED_DMA_2B_IDX           0x100000
 
 #define BRCMF_PCIE_FLAGS_HTOD_SPLIT            0x4000
 #define BRCMF_PCIE_FLAGS_DTOH_SPLIT            0x8000
@@ -147,6 +148,10 @@ enum brcmf_pcie_state {
 #define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
 #define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
 #define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
+#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET  20
+#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET  28
+#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET  36
+#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET  44
 #define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET    0
 #define BRCMF_SHARED_RING_MAX_SUB_QUEUES       52
 
@@ -248,6 +253,13 @@ struct brcmf_pciedev_info {
        bool mbdata_completed;
        bool irq_allocated;
        bool wowl_enabled;
+       u8 dma_idx_sz;
+       void *idxbuf;
+       u32 idxbuf_sz;
+       dma_addr_t idxbuf_dmahandle;
+       u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
+       void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+                         u16 value);
 };
 
 struct brcmf_pcie_ringbuf {
@@ -277,15 +289,6 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
 };
 
 
-/* dma flushing needs implementation for mips and arm platforms. Should
- * be put in util. Note, this is not real flushing. It is virtual non
- * cached memory. Only write buffers should have to be drained. Though
- * this may be different depending on platform......
- */
-#define brcmf_dma_flush(addr, len)
-#define brcmf_dma_invalidate_cache(addr, len)
-
-
 static u32
 brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
 {
@@ -333,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
 }
 
 
+static u16
+brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+       u16 *address = devinfo->idxbuf + mem_offset;
+
+       return (*(address));
+}
+
+
+static void
+brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+                    u16 value)
+{
+       u16 *address = devinfo->idxbuf + mem_offset;
+
+       *(address) = value;
+}
+
+
 static u32
 brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
 {
@@ -878,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
        brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
                  commonring->w_ptr, ring->id);
 
-       brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
+       devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
 
        return 0;
 }
@@ -896,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
        brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
                  commonring->r_ptr, ring->id);
 
-       brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
+       devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
 
        return 0;
 }
@@ -925,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
        if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
                return -EIO;
 
-       commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
+       commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
 
        brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
                  commonring->w_ptr, ring->id);
@@ -943,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
        if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
                return -EIO;
 
-       commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
+       commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
 
        brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
                  commonring->r_ptr, ring->id);
@@ -1048,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
        }
        kfree(devinfo->shared.flowrings);
        devinfo->shared.flowrings = NULL;
+       if (devinfo->idxbuf) {
+               dma_free_coherent(&devinfo->pdev->dev,
+                                 devinfo->idxbuf_sz,
+                                 devinfo->idxbuf,
+                                 devinfo->idxbuf_dmahandle);
+               devinfo->idxbuf = NULL;
+       }
 }
 
 
@@ -1063,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
        u32 addr;
        u32 ring_mem_ptr;
        u32 i;
+       u64 address;
+       u32 bufsz;
        u16 max_sub_queues;
+       u8 idx_offset;
 
        ring_addr = devinfo->shared.ring_info_addr;
        brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
+       addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
+       max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+
+       if (devinfo->dma_idx_sz != 0) {
+               bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
+                       devinfo->dma_idx_sz * 2;
+               devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
+                                                    &devinfo->idxbuf_dmahandle,
+                                                    GFP_KERNEL);
+               if (!devinfo->idxbuf)
+                       devinfo->dma_idx_sz = 0;
+       }
 
-       addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
-       d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
-       addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
-       d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
-       addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
-       h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
-       addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
-       h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+       if (devinfo->dma_idx_sz == 0) {
+               addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
+               d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+               addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
+               d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+               addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
+               h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+               addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
+               h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+               idx_offset = sizeof(u32);
+               devinfo->write_ptr = brcmf_pcie_write_tcm16;
+               devinfo->read_ptr = brcmf_pcie_read_tcm16;
+               brcmf_dbg(PCIE, "Using TCM indices\n");
+       } else {
+               memset(devinfo->idxbuf, 0, bufsz);
+               devinfo->idxbuf_sz = bufsz;
+               idx_offset = devinfo->dma_idx_sz;
+               devinfo->write_ptr = brcmf_pcie_write_idx;
+               devinfo->read_ptr = brcmf_pcie_read_idx;
+
+               h2d_w_idx_ptr = 0;
+               addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
+               address = (u64)devinfo->idxbuf_dmahandle;
+               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+
+               h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
+               addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
+               address += max_sub_queues * idx_offset;
+               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+
+               d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
+               addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
+               address += max_sub_queues * idx_offset;
+               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+
+               d2h_r_idx_ptr = d2h_w_idx_ptr +
+                               BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
+               addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
+               address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
+               brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+               brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+               brcmf_dbg(PCIE, "Using host memory indices\n");
+       }
 
        addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
        ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
@@ -1089,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
                ring->id = i;
                devinfo->shared.commonrings[i] = ring;
 
-               h2d_w_idx_ptr += sizeof(u32);
-               h2d_r_idx_ptr += sizeof(u32);
+               h2d_w_idx_ptr += idx_offset;
+               h2d_r_idx_ptr += idx_offset;
                ring_mem_ptr += BRCMF_RING_MEM_SZ;
        }
 
@@ -1104,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
                ring->id = i;
                devinfo->shared.commonrings[i] = ring;
 
-               d2h_w_idx_ptr += sizeof(u32);
-               d2h_r_idx_ptr += sizeof(u32);
+               d2h_w_idx_ptr += idx_offset;
+               d2h_r_idx_ptr += idx_offset;
                ring_mem_ptr += BRCMF_RING_MEM_SZ;
        }
 
-       addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
-       max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
        devinfo->shared.nrof_flowrings =
                        max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
        rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
@@ -1134,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
                                             ring);
                ring->w_idx_addr = h2d_w_idx_ptr;
                ring->r_idx_addr = h2d_r_idx_ptr;
-               h2d_w_idx_ptr += sizeof(u32);
-               h2d_r_idx_ptr += sizeof(u32);
+               h2d_w_idx_ptr += idx_offset;
+               h2d_r_idx_ptr += idx_offset;
        }
        devinfo->shared.flowrings = rings;
 
        return 0;
 
 fail:
-       brcmf_err("Allocating commonring buffers failed\n");
+       brcmf_err("Allocating ring buffers failed\n");
        brcmf_pcie_release_ringbuffers(devinfo);
        return -ENOMEM;
 }
@@ -1175,7 +1255,6 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
                goto fail;
 
        memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
-       brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
 
        addr = devinfo->shared.tcm_base_address +
               BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
@@ -1193,7 +1272,6 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
                goto fail;
 
        memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
-       brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
 
        addr = devinfo->shared.tcm_base_address +
               BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
@@ -1280,10 +1358,13 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
                brcmf_err("Unsupported PCIE version %d\n", version);
                return -EINVAL;
        }
-       if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
-               brcmf_err("Unsupported legacy TX mode 0x%x\n",
-                         shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
-               return -EINVAL;
+
+       /* check firmware support dma indicies */
+       if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
+               if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
+                       devinfo->dma_idx_sz = sizeof(u16);
+               else
+                       devinfo->dma_idx_sz = sizeof(u32);
        }
 
        addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
index 3d32f4120174d9fe6d3bb0a337cd5fe97fed6b83..dbfc5b18bcb712fe20dee3e048891ee81bf2876c 100644 (file)
@@ -9,6 +9,7 @@ iwlwifi-objs            += iwl-phy-db.o iwl-nvm-parse.o
 iwlwifi-objs           += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
 iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
 iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o
+iwlwifi-objs           += iwl-trans.o
 
 iwlwifi-objs += $(iwlwifi-m)
 
index ba7fc42edf97245e9a8ac05c5316de9079b3391d..852461ffe98febdf5757d3139df2ac010d1204bc 100644 (file)
@@ -112,6 +112,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
                    IEEE80211_HW_QUEUE_CONTROL |
                    IEEE80211_HW_SUPPORTS_PS |
                    IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
+                   IEEE80211_HW_SUPPORT_FAST_XMIT |
                    IEEE80211_HW_WANT_MONITOR_VIF;
 
        hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
index 0afe4946e4f980f2103860ead254ad934f2df2ee..cc35f796d406156286164410aa7d1adcd087c015 100644 (file)
@@ -69,7 +69,7 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  13
+#define IWL7260_UCODE_API_MAX  15
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   12
index ce6321b7d24156269fd553f4409078b1c3fb24df..72040cd0b9794e6790daaa7f887089692ccb1d5e 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX  13
+#define IWL8000_UCODE_API_MAX  15
 
 /* Oldest version we won't warn about */
 #define IWL8000_UCODE_API_OK   12
@@ -122,24 +122,49 @@ static const struct iwl_ht_params iwl8000_ht_params = {
        .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
 };
 
-#define IWL_DEVICE_8000                                                \
-       .ucode_api_max = IWL8000_UCODE_API_MAX,                 \
-       .ucode_api_ok = IWL8000_UCODE_API_OK,                   \
-       .ucode_api_min = IWL8000_UCODE_API_MIN,                 \
-       .device_family = IWL_DEVICE_FAMILY_8000,                \
-       .max_inst_size = IWL60_RTC_INST_SIZE,                   \
-       .max_data_size = IWL60_RTC_DATA_SIZE,                   \
-       .base_params = &iwl8000_base_params,                    \
-       .led_mode = IWL_LED_RF_STATE,                           \
-       .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000,   \
-       .d0i3 = true,                                           \
-       .non_shared_ant = ANT_A,                                \
-       .dccm_offset = IWL8260_DCCM_OFFSET,                     \
-       .dccm_len = IWL8260_DCCM_LEN,                           \
-       .dccm2_offset = IWL8260_DCCM2_OFFSET,                   \
-       .dccm2_len = IWL8260_DCCM2_LEN,                         \
-       .smem_offset = IWL8260_SMEM_OFFSET,                     \
-       .smem_len = IWL8260_SMEM_LEN
+static const struct iwl_tt_params iwl8000_tt_params = {
+       .ct_kill_entry = 115,
+       .ct_kill_exit = 93,
+       .ct_kill_duration = 5,
+       .dynamic_smps_entry = 111,
+       .dynamic_smps_exit = 107,
+       .tx_protection_entry = 112,
+       .tx_protection_exit = 105,
+       .tx_backoff = {
+               {.temperature = 110, .backoff = 200},
+               {.temperature = 111, .backoff = 600},
+               {.temperature = 112, .backoff = 1200},
+               {.temperature = 113, .backoff = 2000},
+               {.temperature = 114, .backoff = 4000},
+       },
+       .support_ct_kill = true,
+       .support_dynamic_smps = true,
+       .support_tx_protection = true,
+       .support_tx_backoff = true,
+};
+
+#define IWL_DEVICE_8000                                                        \
+       .ucode_api_max = IWL8000_UCODE_API_MAX,                         \
+       .ucode_api_ok = IWL8000_UCODE_API_OK,                           \
+       .ucode_api_min = IWL8000_UCODE_API_MIN,                         \
+       .device_family = IWL_DEVICE_FAMILY_8000,                        \
+       .max_inst_size = IWL60_RTC_INST_SIZE,                           \
+       .max_data_size = IWL60_RTC_DATA_SIZE,                           \
+       .base_params = &iwl8000_base_params,                            \
+       .led_mode = IWL_LED_RF_STATE,                                   \
+       .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000,           \
+       .d0i3 = true,                                                   \
+       .non_shared_ant = ANT_A,                                        \
+       .dccm_offset = IWL8260_DCCM_OFFSET,                             \
+       .dccm_len = IWL8260_DCCM_LEN,                                   \
+       .dccm2_offset = IWL8260_DCCM2_OFFSET,                           \
+       .dccm2_len = IWL8260_DCCM2_LEN,                                 \
+       .smem_offset = IWL8260_SMEM_OFFSET,                             \
+       .smem_len = IWL8260_SMEM_LEN,                                   \
+       .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,       \
+       .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,       \
+       .thermal_params = &iwl8000_tt_params,                           \
+       .apmg_not_supported = true
 
 const struct iwl_cfg iwl8260_2n_cfg = {
        .name = "Intel(R) Dual Band Wireless N 8260",
@@ -177,8 +202,6 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-       .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
-       .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
        .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
        .disable_dummy_notification = true,
        .max_ht_ampdu_exponent  = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
@@ -192,8 +215,6 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-       .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
-       .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
        .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
        .bt_shared_single_ant = true,
        .disable_dummy_notification = true,
index 225b6d6b8573056c0686a7b79000634b0cdfcf70..08c14afeb1480aca04d61bd083795eb2aec401c2 100644 (file)
@@ -360,6 +360,7 @@ struct iwl_cfg {
        const u32 smem_offset;
        const u32 smem_len;
        const struct iwl_tt_params *thermal_params;
+       bool apmg_not_supported;
 };
 
 /*
index 223b8752f924839bcff4028f66213032759ed124..948ce0802fa7ceae995d0257a6a3f8dace6ccf14 100644 (file)
@@ -1,6 +1,7 @@
 /******************************************************************************
  *
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -64,19 +65,21 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
 
 TRACE_EVENT(iwlwifi_dev_rx,
        TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
-                void *rxbuf, size_t len),
-       TP_ARGS(dev, trans, rxbuf, len),
+                struct iwl_rx_packet *pkt, size_t len),
+       TP_ARGS(dev, trans, pkt, len),
        TP_STRUCT__entry(
                DEV_ENTRY
-               __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
+               __field(u8, cmd)
+               __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, pkt, len))
        ),
        TP_fast_assign(
                DEV_ASSIGN;
-               memcpy(__get_dynamic_array(rxbuf), rxbuf,
-                      iwl_rx_trace_len(trans, rxbuf, len));
+               __entry->cmd = pkt->hdr.cmd;
+               memcpy(__get_dynamic_array(rxbuf), pkt,
+                      iwl_rx_trace_len(trans, pkt, len));
        ),
        TP_printk("[%s] RX cmd %#.2x",
-                 __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
+                 __get_str(dev), __entry->cmd)
 );
 
 TRACE_EVENT(iwlwifi_dev_tx,
index 7267152e7dc7705aaa514237c17ed908b9e4919d..6685259927f81bd979c20b90d0f9970358c98d46 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -423,13 +423,19 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
 {
        const struct iwl_ucode_api *ucode_api = (void *)data;
        u32 api_index = le32_to_cpu(ucode_api->api_index);
+       u32 api_flags = le32_to_cpu(ucode_api->api_flags);
+       int i;
 
-       if (api_index >= IWL_API_ARRAY_SIZE) {
+       if (api_index >= IWL_API_MAX_BITS / 32) {
                IWL_ERR(drv, "api_index larger than supported by driver\n");
-               return -EINVAL;
+               /* don't return an error so we can load FW that has more bits */
+               return 0;
        }
 
-       capa->api[api_index] = le32_to_cpu(ucode_api->api_flags);
+       for (i = 0; i < 32; i++) {
+               if (api_flags & BIT(i))
+                       __set_bit(i + 32 * api_index, capa->_api);
+       }
 
        return 0;
 }
@@ -439,13 +445,19 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
 {
        const struct iwl_ucode_capa *ucode_capa = (void *)data;
        u32 api_index = le32_to_cpu(ucode_capa->api_index);
+       u32 api_flags = le32_to_cpu(ucode_capa->api_capa);
+       int i;
 
-       if (api_index >= IWL_CAPABILITIES_ARRAY_SIZE) {
+       if (api_index >= IWL_CAPABILITIES_MAX_BITS / 32) {
                IWL_ERR(drv, "api_index larger than supported by driver\n");
-               return -EINVAL;
+               /* don't return an error so we can load FW that has more bits */
+               return 0;
        }
 
-       capa->capa[api_index] = le32_to_cpu(ucode_capa->api_capa);
+       for (i = 0; i < 32; i++) {
+               if (api_flags & BIT(i))
+                       __set_bit(i + 32 * api_index, capa->_capa);
+       }
 
        return 0;
 }
@@ -1148,7 +1160,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                goto try_again;
 
-       if (drv->fw.ucode_capa.api[0] & IWL_UCODE_TLV_API_NEW_VERSION)
+       if (fw_has_api(&drv->fw.ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION))
                api_ver = drv->fw.ucode_ver;
        else
                api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
@@ -1239,6 +1251,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
                sizeof(struct iwl_fw_dbg_trigger_txq_timer);
        trigger_tlv_sz[FW_DBG_TRIGGER_TIME_EVENT] =
                sizeof(struct iwl_fw_dbg_trigger_time_event);
+       trigger_tlv_sz[FW_DBG_TRIGGER_BA] =
+               sizeof(struct iwl_fw_dbg_trigger_ba);
 
        for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
                if (pieces->dbg_trigger_tlv[i]) {
index d45dc021cda2c0715b8d7e740ff90b46589ae141..d56064861a9c353dfb9fcf1720e1abde6c3fcf9d 100644 (file)
@@ -438,12 +438,6 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
 #define RX_QUEUE_MASK                         255
 #define RX_QUEUE_SIZE_LOG                     8
 
-/*
- * RX related structures and functions
- */
-#define RX_FREE_BUFFERS 64
-#define RX_LOW_WATERMARK 8
-
 /**
  * struct iwl_rb_status - reserve buffer status
  *     host memory mapped FH registers
index 251bf8dc4a12133b4ae77757170436c67219afc9..e57dbd0ef2e1f10f8d16bd26537f2ee829b5eade 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -254,6 +254,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
  *     detection.
  * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
  *     events.
+ * @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
  */
 enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_INVALID = 0,
@@ -267,6 +268,7 @@ enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_RSSI,
        FW_DBG_TRIGGER_TXQ_TIMERS,
        FW_DBG_TRIGGER_TIME_EVENT,
+       FW_DBG_TRIGGER_BA,
 
        /* must be last */
        FW_DBG_TRIGGER_MAX,
index c7cfc38a2644167ba89072618872e915e01d3726..a9b5ae4ebec021277efc454730d03b562add3210 100644 (file)
@@ -237,6 +237,8 @@ enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_GO_UAPSD            = BIT(30),
 };
 
+typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
+
 /**
  * enum iwl_ucode_tlv_api - ucode api
  * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
@@ -255,22 +257,27 @@ enum iwl_ucode_tlv_flag {
  * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params
  * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10
  * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format
+ * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority
+ *     instead of 3.
  */
 enum iwl_ucode_tlv_api {
-       IWL_UCODE_TLV_API_BT_COEX_SPLIT         = BIT(3),
-       IWL_UCODE_TLV_API_FRAGMENTED_SCAN       = BIT(8),
-       IWL_UCODE_TLV_API_WIFI_MCC_UPDATE       = BIT(9),
-       IWL_UCODE_TLV_API_HDC_PHASE_0           = BIT(10),
-       IWL_UCODE_TLV_API_TX_POWER_DEV          = BIT(11),
-       IWL_UCODE_TLV_API_BASIC_DWELL           = BIT(13),
-       IWL_UCODE_TLV_API_SCD_CFG               = BIT(15),
-       IWL_UCODE_TLV_API_SINGLE_SCAN_EBS       = BIT(16),
-       IWL_UCODE_TLV_API_ASYNC_DTM             = BIT(17),
-       IWL_UCODE_TLV_API_LQ_SS_PARAMS          = BIT(18),
-       IWL_UCODE_TLV_API_STATS_V10             = BIT(19),
-       IWL_UCODE_TLV_API_NEW_VERSION           = BIT(20),
+       IWL_UCODE_TLV_API_BT_COEX_SPLIT         = (__force iwl_ucode_tlv_api_t)3,
+       IWL_UCODE_TLV_API_FRAGMENTED_SCAN       = (__force iwl_ucode_tlv_api_t)8,
+       IWL_UCODE_TLV_API_WIFI_MCC_UPDATE       = (__force iwl_ucode_tlv_api_t)9,
+       IWL_UCODE_TLV_API_HDC_PHASE_0           = (__force iwl_ucode_tlv_api_t)10,
+       IWL_UCODE_TLV_API_TX_POWER_DEV          = (__force iwl_ucode_tlv_api_t)11,
+       IWL_UCODE_TLV_API_BASIC_DWELL           = (__force iwl_ucode_tlv_api_t)13,
+       IWL_UCODE_TLV_API_SCD_CFG               = (__force iwl_ucode_tlv_api_t)15,
+       IWL_UCODE_TLV_API_SINGLE_SCAN_EBS       = (__force iwl_ucode_tlv_api_t)16,
+       IWL_UCODE_TLV_API_ASYNC_DTM             = (__force iwl_ucode_tlv_api_t)17,
+       IWL_UCODE_TLV_API_LQ_SS_PARAMS          = (__force iwl_ucode_tlv_api_t)18,
+       IWL_UCODE_TLV_API_STATS_V10             = (__force iwl_ucode_tlv_api_t)19,
+       IWL_UCODE_TLV_API_NEW_VERSION           = (__force iwl_ucode_tlv_api_t)20,
+       IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY     = (__force iwl_ucode_tlv_api_t)24,
 };
 
+typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
+
 /**
  * enum iwl_ucode_tlv_capa - ucode capabilities
  * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
@@ -290,6 +297,7 @@ enum iwl_ucode_tlv_api {
  *     which also implies support for the scheduler configuration command
  * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching
  * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
+ * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command
  * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
  * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
  * @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
@@ -299,22 +307,23 @@ enum iwl_ucode_tlv_api {
  * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
  */
 enum iwl_ucode_tlv_capa {
-       IWL_UCODE_TLV_CAPA_D0I3_SUPPORT                 = BIT(0),
-       IWL_UCODE_TLV_CAPA_LAR_SUPPORT                  = BIT(1),
-       IWL_UCODE_TLV_CAPA_UMAC_SCAN                    = BIT(2),
-       IWL_UCODE_TLV_CAPA_BEAMFORMER                   = BIT(3),
-       IWL_UCODE_TLV_CAPA_TDLS_SUPPORT                 = BIT(6),
-       IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT    = BIT(8),
-       IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT      = BIT(9),
-       IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT       = BIT(10),
-       IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT         = BIT(11),
-       IWL_UCODE_TLV_CAPA_DQA_SUPPORT                  = BIT(12),
-       IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH          = BIT(13),
-       IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT              = BIT(18),
-       IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS           = BIT(22),
-       IWL_UCODE_TLV_CAPA_BT_COEX_PLCR                 = BIT(28),
-       IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC                = BIT(29),
-       IWL_UCODE_TLV_CAPA_BT_COEX_RRC                  = BIT(30),
+       IWL_UCODE_TLV_CAPA_D0I3_SUPPORT                 = (__force iwl_ucode_tlv_capa_t)0,
+       IWL_UCODE_TLV_CAPA_LAR_SUPPORT                  = (__force iwl_ucode_tlv_capa_t)1,
+       IWL_UCODE_TLV_CAPA_UMAC_SCAN                    = (__force iwl_ucode_tlv_capa_t)2,
+       IWL_UCODE_TLV_CAPA_BEAMFORMER                   = (__force iwl_ucode_tlv_capa_t)3,
+       IWL_UCODE_TLV_CAPA_TDLS_SUPPORT                 = (__force iwl_ucode_tlv_capa_t)6,
+       IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT    = (__force iwl_ucode_tlv_capa_t)8,
+       IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT      = (__force iwl_ucode_tlv_capa_t)9,
+       IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT       = (__force iwl_ucode_tlv_capa_t)10,
+       IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT         = (__force iwl_ucode_tlv_capa_t)11,
+       IWL_UCODE_TLV_CAPA_DQA_SUPPORT                  = (__force iwl_ucode_tlv_capa_t)12,
+       IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH          = (__force iwl_ucode_tlv_capa_t)13,
+       IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT              = (__force iwl_ucode_tlv_capa_t)18,
+       IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT         = (__force iwl_ucode_tlv_capa_t)19,
+       IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS           = (__force iwl_ucode_tlv_capa_t)22,
+       IWL_UCODE_TLV_CAPA_BT_COEX_PLCR                 = (__force iwl_ucode_tlv_capa_t)28,
+       IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC                = (__force iwl_ucode_tlv_capa_t)29,
+       IWL_UCODE_TLV_CAPA_BT_COEX_RRC                  = (__force iwl_ucode_tlv_capa_t)30,
 };
 
 /* The default calibrate table size if not specified by firmware file */
@@ -325,13 +334,14 @@ enum iwl_ucode_tlv_capa {
 /* The default max probe length if not specified by the firmware file */
 #define IWL_DEFAULT_MAX_PROBE_LENGTH   200
 
+#define IWL_API_MAX_BITS               64
+#define IWL_CAPABILITIES_MAX_BITS      64
+
 /*
  * For 16.0 uCode and above, there is no differentiation between sections,
  * just an offset to the HW address.
  */
 #define IWL_UCODE_SECTION_MAX 12
-#define IWL_API_ARRAY_SIZE     1
-#define IWL_CAPABILITIES_ARRAY_SIZE    1
 #define CPU1_CPU2_SEPARATOR_SECTION    0xFFFFCCCC
 
 /* uCode version contains 4 values: Major/Minor/API/Serial */
@@ -424,11 +434,13 @@ struct iwl_fw_dbg_reg_op {
  * @SMEM_MODE: monitor stores the data in SMEM
  * @EXTERNAL_MODE: monitor stores the data in allocated DRAM
  * @MARBH_MODE: monitor stores the data in MARBH buffer
+ * @MIPI_MODE: monitor outputs the data through the MIPI interface
  */
 enum iwl_fw_dbg_monitor_mode {
        SMEM_MODE = 0,
        EXTERNAL_MODE = 1,
        MARBH_MODE = 2,
+       MIPI_MODE = 3,
 };
 
 /**
@@ -660,6 +672,33 @@ struct iwl_fw_dbg_trigger_time_event {
        } __packed time_events[16];
 } __packed;
 
+/**
+ * struct iwl_fw_dbg_trigger_ba - configures BlockAck related trigger
+ * rx_ba_start: tid bitmap to configure on what tid the trigger should occur
+ *     when an Rx BlockAck session is started.
+ * rx_ba_stop: tid bitmap to configure on what tid the trigger should occur
+ *     when an Rx BlockAck session is stopped.
+ * tx_ba_start: tid bitmap to configure on what tid the trigger should occur
+ *     when a Tx BlockAck session is started.
+ * tx_ba_stop: tid bitmap to configure on what tid the trigger should occur
+ *     when a Tx BlockAck session is stopped.
+ * rx_bar: tid bitmap to configure on what tid the trigger should occur
+ *     when a BAR is received (for a Tx BlockAck session).
+ * tx_bar: tid bitmap to configure on what tid the trigger should occur
+ *     when a BAR is send (for an Rx BlocAck session).
+ * frame_timeout: tid bitmap to configure on what tid the trigger should occur
+ *     when a frame times out in the reodering buffer.
+ */
+struct iwl_fw_dbg_trigger_ba {
+       __le16 rx_ba_start;
+       __le16 rx_ba_stop;
+       __le16 tx_ba_start;
+       __le16 tx_ba_stop;
+       __le16 rx_bar;
+       __le16 tx_bar;
+       __le16 frame_timeout;
+} __packed;
+
 /**
  * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
  * @id: conf id
index cf75bafae51da0f60255d9a7f98f7d2f5e18bcac..3e3c9d8b3c37dd93b7ab59529bf5c7b3cd9d7ae0 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -105,10 +105,24 @@ struct iwl_ucode_capabilities {
        u32 n_scan_channels;
        u32 standard_phy_calibration_size;
        u32 flags;
-       u32 api[IWL_API_ARRAY_SIZE];
-       u32 capa[IWL_CAPABILITIES_ARRAY_SIZE];
+       unsigned long _api[BITS_TO_LONGS(IWL_API_MAX_BITS)];
+       unsigned long _capa[BITS_TO_LONGS(IWL_CAPABILITIES_MAX_BITS)];
 };
 
+static inline bool
+fw_has_api(const struct iwl_ucode_capabilities *capabilities,
+          iwl_ucode_tlv_api_t api)
+{
+       return test_bit((__force long)api, capabilities->_api);
+}
+
+static inline bool
+fw_has_capa(const struct iwl_ucode_capabilities *capabilities,
+           iwl_ucode_tlv_capa_t capa)
+{
+       return test_bit((__force long)capa, capabilities->_capa);
+}
+
 /* one for each uCode image (inst/data, init/runtime/wowlan) */
 struct fw_desc {
        const void *data;       /* vmalloc'ed data */
@@ -205,6 +219,8 @@ static inline const char *get_fw_dbg_mode_string(int mode)
                return "EXTERNAL_DRAM";
        case MARBH_MODE:
                return "MARBH";
+       case MIPI_MODE:
+               return "MIPI";
        default:
                return "UNKNOWN";
        }
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
new file mode 100644 (file)
index 0000000..9f8bcef
--- /dev/null
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * 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) 2015 Intel Mobile Communications GmbH
+ *
+ * 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 COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015 Intel Mobile Communications GmbH
+ * 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.
+ *
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include "iwl-trans.h"
+
+struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
+                                 struct device *dev,
+                                 const struct iwl_cfg *cfg,
+                                 const struct iwl_trans_ops *ops,
+                                 size_t dev_cmd_headroom)
+{
+       struct iwl_trans *trans;
+#ifdef CONFIG_LOCKDEP
+       static struct lock_class_key __key;
+#endif
+
+       trans = kzalloc(sizeof(*trans) + priv_size, GFP_KERNEL);
+       if (!trans)
+               return NULL;
+
+#ifdef CONFIG_LOCKDEP
+       lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
+                        &__key, 0);
+#endif
+
+       trans->dev = dev;
+       trans->cfg = cfg;
+       trans->ops = ops;
+       trans->dev_cmd_headroom = dev_cmd_headroom;
+
+       snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
+                "iwl_cmd_pool:%s", dev_name(trans->dev));
+       trans->dev_cmd_pool =
+               kmem_cache_create(trans->dev_cmd_pool_name,
+                                 sizeof(struct iwl_device_cmd)
+                                 + trans->dev_cmd_headroom,
+                                 sizeof(void *),
+                                 SLAB_HWCACHE_ALIGN,
+                                 NULL);
+       if (!trans->dev_cmd_pool)
+               goto free;
+
+       return trans;
+ free:
+       kfree(trans);
+       return NULL;
+}
+
+void iwl_trans_free(struct iwl_trans *trans)
+{
+       kmem_cache_destroy(trans->dev_cmd_pool);
+       kfree(trans);
+}
index 56254a837214ffad421a7b7a14a9eaec3d7dc029..87a230a7f4b605b8b6db80b69b3db7bc95b59e2f 100644 (file)
@@ -641,6 +641,8 @@ struct iwl_trans {
 
        enum iwl_d0i3_mode d0i3_mode;
 
+       bool wowlan_d0i3;
+
        /* pointer to trans specific struct */
        /*Ensure that this pointer will always be aligned to sizeof pointer */
        char trans_specific[0] __aligned(sizeof(void *));
@@ -1010,20 +1012,20 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
                iwl_op_mode_nic_error(trans->op_mode);
 }
 
+/*****************************************************
+ * transport helper functions
+ *****************************************************/
+struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
+                                 struct device *dev,
+                                 const struct iwl_cfg *cfg,
+                                 const struct iwl_trans_ops *ops,
+                                 size_t dev_cmd_headroom);
+void iwl_trans_free(struct iwl_trans *trans);
+
 /*****************************************************
 * driver (transport) register/unregister functions
 ******************************************************/
 int __must_check iwl_pci_register_driver(void);
 void iwl_pci_unregister_driver(void);
 
-static inline void trans_lockdep_init(struct iwl_trans *trans)
-{
-#ifdef CONFIG_LOCKDEP
-       static struct lock_class_key __key;
-
-       lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
-                        &__key, 0);
-#endif
-}
-
 #endif /* __iwl_trans_h__ */
index 13a0a03158deb0d1d884b390dfb2e7e3751b5ee2..b4737e296c927582063409917951a210e8ffa74e 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -408,23 +408,12 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
 
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 {
-       struct iwl_bt_coex_cmd *bt_cmd;
-       struct iwl_host_cmd cmd = {
-               .id = BT_CONFIG,
-               .len = { sizeof(*bt_cmd), },
-               .dataflags = { IWL_HCMD_DFL_NOCOPY, },
-       };
-       int ret;
+       struct iwl_bt_coex_cmd bt_cmd = {};
        u32 mode;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_send_bt_init_conf_old(mvm);
 
-       bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
-       if (!bt_cmd)
-               return -ENOMEM;
-       cmd.data[0] = bt_cmd;
-
        lockdep_assert_held(&mvm->mutex);
 
        if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
@@ -440,36 +429,33 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
                        mode = 0;
                }
 
-               bt_cmd->mode = cpu_to_le32(mode);
+               bt_cmd.mode = cpu_to_le32(mode);
                goto send_cmd;
        }
 
        mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE;
-       bt_cmd->mode = cpu_to_le32(mode);
+       bt_cmd.mode = cpu_to_le32(mode);
 
        if (IWL_MVM_BT_COEX_SYNC2SCO)
-               bt_cmd->enabled_modules |=
+               bt_cmd.enabled_modules |=
                        cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
 
        if (iwl_mvm_bt_is_plcr_supported(mvm))
-               bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
+               bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
 
        if (IWL_MVM_BT_COEX_MPLUT) {
-               bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
-               bt_cmd->enabled_modules |=
+               bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
+               bt_cmd.enabled_modules |=
                        cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
        }
 
-       bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
+       bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
 
 send_cmd:
        memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
        memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
 
-       ret = iwl_mvm_send_cmd(mvm, &cmd);
-
-       kfree(bt_cmd);
-       return ret;
+       return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, 0, sizeof(bt_cmd), &bt_cmd);
 }
 
 static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
@@ -746,7 +732,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_rx_bt_coex_notif_old(mvm, rxb, dev_cmd);
 
        IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
@@ -770,52 +756,14 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
        return 0;
 }
 
-static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
-                                  struct ieee80211_vif *vif)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_bt_iterator_data *data = _data;
-       struct iwl_mvm *mvm = data->mvm;
-
-       struct ieee80211_sta *sta;
-       struct iwl_mvm_sta *mvmsta;
-
-       struct ieee80211_chanctx_conf *chanctx_conf;
-
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(vif->chanctx_conf);
-       /* If channel context is invalid or not on 2.4GHz - don't count it */
-       if (!chanctx_conf ||
-           chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
-               rcu_read_unlock();
-               return;
-       }
-       rcu_read_unlock();
-
-       if (vif->type != NL80211_IFTYPE_STATION ||
-           mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
-               return;
-
-       sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
-                                       lockdep_is_held(&mvm->mutex));
-
-       /* This can happen if the station has been removed right now */
-       if (IS_ERR_OR_NULL(sta))
-               return;
-
-       mvmsta = iwl_mvm_sta_from_mac80211(sta);
-}
-
 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                           enum ieee80211_rssi_event_data rssi_event)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_bt_iterator_data data = {
-               .mvm = mvm,
-       };
        int ret;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+       if (!fw_has_api(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
                iwl_mvm_bt_rssi_event_old(mvm, vif, rssi_event);
                return;
        }
@@ -853,10 +801,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        if (ret)
                IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
-
-       ieee80211_iterate_active_interfaces_atomic(
-               mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-               iwl_mvm_bt_rssi_iterator, &data);
 }
 
 #define LINK_QUAL_AGG_TIME_LIMIT_DEF   (4000)
@@ -870,7 +814,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
        struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
        enum iwl_bt_coex_lut_type lut_type;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
 
        if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
@@ -897,7 +841,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
        struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
        enum iwl_bt_coex_lut_type lut_type;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
 
        if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
@@ -927,7 +871,7 @@ bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
        if (ant & mvm->cfg->non_shared_ant)
                return true;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
 
        return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
@@ -940,10 +884,10 @@ bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
        if (mvm->cfg->bt_shared_single_ant)
                return true;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
 
-       return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF;
+       return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC;
 }
 
 bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
@@ -951,7 +895,7 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
 {
        u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_bt_coex_is_tpc_allowed_old(mvm, band);
 
        if (band != IEEE80211_BAND_2GHZ)
@@ -994,7 +938,8 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 
 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
 {
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+       if (!fw_has_api(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
                iwl_mvm_bt_coex_vif_change_old(mvm);
                return;
        }
@@ -1012,7 +957,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
        u8 __maybe_unused lower_bound, upper_bound;
        u8 lut;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BT_COEX_SPLIT))
                return iwl_mvm_rx_ant_coupling_notif_old(mvm, rxb, dev_cmd);
 
        if (!iwl_mvm_bt_is_plcr_supported(mvm))
index d30f168dcafe3cc44deedab0afc3e11529eb0110..4165d104e4c379dde727f01d585904dec6030deb 100644 (file)
@@ -761,7 +761,7 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 
 static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
 {
-       iwl_mvm_cancel_scan(mvm);
+       iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);
 
        iwl_trans_stop_device(mvm->trans);
 
@@ -1170,7 +1170,8 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
        iwl_trans_suspend(mvm->trans);
-       if (wowlan->any) {
+       mvm->trans->wowlan_d0i3 = wowlan->any;
+       if (mvm->trans->wowlan_d0i3) {
                /* 'any' trigger means d0i3 usage */
                if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
                        int ret = iwl_mvm_enter_d0i3_sync(mvm);
@@ -1785,7 +1786,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
        for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
                struct iwl_scan_offload_profile_match *fw_match;
                struct cfg80211_wowlan_nd_match *match;
-               int n_channels = 0;
+               int idx, n_channels = 0;
 
                fw_match = &query.matches[i];
 
@@ -1800,8 +1801,12 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
 
                net_detect->matches[net_detect->n_matches++] = match;
 
-               match->ssid.ssid_len = mvm->nd_match_sets[i].ssid.ssid_len;
-               memcpy(match->ssid.ssid, mvm->nd_match_sets[i].ssid.ssid,
+               /* We inverted the order of the SSIDs in the scan
+                * request, so invert the index here.
+                */
+               idx = mvm->n_nd_match_sets - i - 1;
+               match->ssid.ssid_len = mvm->nd_match_sets[idx].ssid.ssid_len;
+               memcpy(match->ssid.ssid, mvm->nd_match_sets[idx].ssid.ssid,
                       match->ssid.ssid_len);
 
                if (mvm->n_nd_channels < n_channels)
index 5f37eab5008d7a9ebe1719204f024c9d70e01434..5c8a65de0e775a2327d392f617c4433bdd096f6d 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -190,6 +190,21 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
        return ret ?: count;
 }
 
+static ssize_t iwl_dbgfs_tx_pwr_lmt_read(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ieee80211_vif *vif = file->private_data;
+       char buf[64];
+       int bufsz = sizeof(buf);
+       int pos;
+
+       pos = scnprintf(buf, bufsz, "bss limit = %d\n",
+                       vif->bss_conf.txpower);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
 static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
                                        char __user *user_buf,
                                        size_t count, loff_t *ppos)
@@ -607,6 +622,7 @@ static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
        } while (0)
 
 MVM_DEBUGFS_READ_FILE_OPS(mac_params);
+MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
@@ -641,6 +657,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
                                         S_IRUSR);
 
+       MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, S_IRUSR);
        MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
        MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
                                 S_IRUSR | S_IWUSR);
index 9ac04c1ea7063d985980a5237fe705c1bba7186c..ffb4b5cef27570bbe4af0670683a41891b673330 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -493,7 +493,8 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
 
        mutex_lock(&mvm->mutex);
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+       if (!fw_has_api(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
                struct iwl_bt_coex_profile_notif_old *notif =
                        &mvm->last_bt_notif_old;
 
@@ -550,7 +551,8 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
 
        mutex_lock(&mvm->mutex);
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+       if (!fw_has_api(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
                struct iwl_bt_coex_ci_cmd_old *cmd = &mvm->last_bt_ci_cmd_old;
 
                pos += scnprintf(buf+pos, bufsz-pos,
@@ -916,7 +918,8 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
 
        if (mvm->scan_rx_ant != scan_rx_ant) {
                mvm->scan_rx_ant = scan_rx_ant;
-               if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
+               if (fw_has_capa(&mvm->fw->ucode_capa,
+                               IWL_UCODE_TLV_CAPA_UMAC_SCAN))
                        iwl_mvm_config_scan(mvm);
        }
 
@@ -1356,6 +1359,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
        PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
        PRINT_MVM_REF(IWL_MVM_REF_SCAN);
        PRINT_MVM_REF(IWL_MVM_REF_ROC);
+       PRINT_MVM_REF(IWL_MVM_REF_ROC_AUX);
        PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
        PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
        PRINT_MVM_REF(IWL_MVM_REF_USER);
index be1a0a1270771d02b3371c8db71498f3f718cdd5..5e4cbdb44c607ec8399bae489f28990dc907eaeb 100644 (file)
@@ -294,6 +294,7 @@ enum iwl_scan_ebs_status {
        IWL_SCAN_EBS_SUCCESS,
        IWL_SCAN_EBS_FAILED,
        IWL_SCAN_EBS_CHAN_NOT_FOUND,
+       IWL_SCAN_EBS_INACTIVE,
 };
 
 /**
@@ -431,6 +432,17 @@ enum iwl_scan_priority {
        IWL_SCAN_PRIORITY_HIGH,
 };
 
+enum iwl_scan_priority_ext {
+       IWL_SCAN_PRIORITY_EXT_0_LOWEST,
+       IWL_SCAN_PRIORITY_EXT_1,
+       IWL_SCAN_PRIORITY_EXT_2,
+       IWL_SCAN_PRIORITY_EXT_3,
+       IWL_SCAN_PRIORITY_EXT_4,
+       IWL_SCAN_PRIORITY_EXT_5,
+       IWL_SCAN_PRIORITY_EXT_6,
+       IWL_SCAN_PRIORITY_EXT_7_HIGHEST,
+};
+
 /**
  * iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
  * @reserved1: for alignment and future use
@@ -837,4 +849,27 @@ struct iwl_scan_offload_profiles_query {
        struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
 } __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
 
+/**
+ * struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration
+ * @uid: scan id, &enum iwl_umac_scan_uid_offsets
+ * @scanned_channels: number of channels scanned and number of valid elements in
+ *     results array
+ * @status: one of SCAN_COMP_STATUS_*
+ * @bt_status: BT on/off status
+ * @last_channel: last channel that was scanned
+ * @tsf_low: TSF timer (lower half) in usecs
+ * @tsf_high: TSF timer (higher half) in usecs
+ * @results: array of scan results, only "scanned_channels" of them are valid
+ */
+struct iwl_umac_scan_iter_complete_notif {
+       __le32 uid;
+       u8 scanned_channels;
+       u8 status;
+       u8 bt_status;
+       u8 last_channel;
+       __le32 tsf_low;
+       __le32 tsf_high;
+       struct iwl_scan_results_notif results[];
+} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */
+
 #endif
index 56db2ba52da067bcae738f4007535a4b522d4af5..16e9ef49397f4d055b788f970f1b74bf2712e5e7 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,6 +108,7 @@ enum {
        ANTENNA_COUPLING_NOTIFICATION = 0xa,
 
        /* UMAC scan commands */
+       SCAN_ITERATION_COMPLETE_UMAC = 0xb5,
        SCAN_CFG_CMD = 0xc,
        SCAN_REQ_UMAC = 0xd,
        SCAN_ABORT_UMAC = 0xe,
@@ -170,12 +171,8 @@ enum {
        /* Thermal Throttling*/
        REPLY_THERMAL_MNG_BACKOFF = 0x7e,
 
-       /* Scanning */
-       SCAN_REQUEST_CMD = 0x80,
-       SCAN_ABORT_CMD = 0x81,
-       SCAN_START_NOTIFICATION = 0x82,
-       SCAN_RESULTS_NOTIFICATION = 0x83,
-       SCAN_COMPLETE_NOTIFICATION = 0x84,
+       /* Set/Get DC2DC frequency tune */
+       DC2DC_CONFIG_CMD = 0x83,
 
        /* NVM */
        NVM_ACCESS_CMD = 0x88,
@@ -1395,6 +1392,49 @@ struct iwl_mvm_marker {
        __le32 metadata[0];
 } __packed; /* MARKER_API_S_VER_1 */
 
+/*
+ * enum iwl_dc2dc_config_id - flag ids
+ *
+ * Ids of dc2dc configuration flags
+ */
+enum iwl_dc2dc_config_id {
+       DCDC_LOW_POWER_MODE_MSK_SET  = 0x1, /* not used */
+       DCDC_FREQ_TUNE_SET = 0x2,
+}; /* MARKER_ID_API_E_VER_1 */
+
+/**
+ * struct iwl_dc2dc_config_cmd - configure dc2dc values
+ *
+ * (DC2DC_CONFIG_CMD = 0x83)
+ *
+ * Set/Get & configure dc2dc values.
+ * The command always returns the current dc2dc values.
+ *
+ * @flags: set/get dc2dc
+ * @enable_low_power_mode: not used.
+ * @dc2dc_freq_tune0: frequency divider - digital domain
+ * @dc2dc_freq_tune1: frequency divider - analog domain
+ */
+struct iwl_dc2dc_config_cmd {
+       __le32 flags;
+       __le32 enable_low_power_mode; /* not used */
+       __le32 dc2dc_freq_tune0;
+       __le32 dc2dc_freq_tune1;
+} __packed; /* DC2DC_CONFIG_CMD_API_S_VER_1 */
+
+/**
+ * struct iwl_dc2dc_config_resp - response for iwl_dc2dc_config_cmd
+ *
+ * Current dc2dc values returned by the FW.
+ *
+ * @dc2dc_freq_tune0: frequency divider - digital domain
+ * @dc2dc_freq_tune1: frequency divider - analog domain
+ */
+struct iwl_dc2dc_config_resp {
+       __le32 dc2dc_freq_tune0;
+       __le32 dc2dc_freq_tune1;
+} __packed; /* DC2DC_CONFIG_RESP_API_S_VER_1 */
+
 /***********************************
  * Smart Fifo API
  ***********************************/
index 0601445599f2b98e51e2fc08bcb320ec7f78cb2c..eb10c5ee4a1407c5b02babe009a899e9f747d6c9 100644 (file)
@@ -623,7 +623,7 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
        if (!mvm->trans->ltr_enabled)
                return 0;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_HDC_PHASE_0))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_HDC_PHASE_0))
                return iwl_mvm_config_ltr_v1(mvm);
 
        return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
@@ -662,9 +662,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
                 * device that are triggered by the INIT firwmare (MFUART).
                 */
                _iwl_trans_stop_device(mvm->trans, false);
-               _iwl_trans_start_hw(mvm->trans, false);
+               ret = _iwl_trans_start_hw(mvm->trans, false);
                if (ret)
-                       return ret;
+                       goto error;
        }
 
        if (iwlmvm_mod_params.init_dbg)
@@ -754,7 +754,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
                        goto error;
        }
 
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
                ret = iwl_mvm_config_scan(mvm);
                if (ret)
                        goto error;
index c131ce6d168a4e6ab15483751bfe21304eb92b88..08367fbc3bc43d15b89c8dbab7bd31becd038606 100644 (file)
@@ -318,7 +318,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
        resp = iwl_mvm_update_mcc(mvm, alpha2, src_id);
        if (IS_ERR_OR_NULL(resp)) {
                IWL_DEBUG_LAR(mvm, "Could not get update from FW %d\n",
-                             PTR_RET(resp));
+                             PTR_ERR_OR_ZERO(resp));
                goto out;
        }
 
@@ -334,7 +334,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
        kfree(resp);
        if (IS_ERR_OR_NULL(regd)) {
                IWL_DEBUG_LAR(mvm, "Could not get parse update from FW %d\n",
-                             PTR_RET(regd));
+                             PTR_ERR_OR_ZERO(regd));
                goto out;
        }
 
@@ -415,6 +415,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 {
        struct ieee80211_hw *hw = mvm->hw;
        int num_mac, ret, i;
+       static const u32 mvm_ciphers[] = {
+               WLAN_CIPHER_SUITE_WEP40,
+               WLAN_CIPHER_SUITE_WEP104,
+               WLAN_CIPHER_SUITE_TKIP,
+               WLAN_CIPHER_SUITE_CCMP,
+       };
 
        /* Tell mac80211 our characteristics */
        hw->flags = IEEE80211_HW_SIGNAL_DBM |
@@ -428,6 +434,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                    IEEE80211_HW_TIMING_BEACON_ONLY |
                    IEEE80211_HW_CONNECTION_MONITOR |
                    IEEE80211_HW_CHANCTX_STA_CSA |
+                   IEEE80211_HW_SUPPORT_FAST_XMIT |
                    IEEE80211_HW_SUPPORTS_CLONED_SKBS;
 
        hw->queues = mvm->first_agg_queue;
@@ -440,19 +447,38 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
        hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
 
+       BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 2);
+       memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
+       hw->wiphy->n_cipher_suites = ARRAY_SIZE(mvm_ciphers);
+       hw->wiphy->cipher_suites = mvm->ciphers;
+
        /*
         * Enable 11w if advertised by firmware and software crypto
         * is not enabled (as the firmware will interpret some mgmt
         * packets, so enabling it with software crypto isn't safe)
         */
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP &&
-           !iwlwifi_mod_params.sw_crypto)
+           !iwlwifi_mod_params.sw_crypto) {
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
+               mvm->ciphers[hw->wiphy->n_cipher_suites] =
+                       WLAN_CIPHER_SUITE_AES_CMAC;
+               hw->wiphy->n_cipher_suites++;
+       }
+
+       /* currently FW API supports only one optional cipher scheme */
+       if (mvm->fw->cs[0].cipher) {
+               mvm->hw->n_cipher_schemes = 1;
+               mvm->hw->cipher_schemes = &mvm->fw->cs[0];
+               mvm->ciphers[hw->wiphy->n_cipher_suites] =
+                       mvm->fw->cs[0].cipher;
+               hw->wiphy->n_cipher_suites++;
+       }
 
        hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
        hw->wiphy->features |=
                NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
-               NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+               NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
+               NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
 
        hw->sta_data_size = sizeof(struct iwl_mvm_sta);
        hw->vif_data_size = sizeof(struct iwl_mvm_vif);
@@ -509,10 +535,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
 
+       BUILD_BUG_ON(IWL_MVM_SCAN_STOPPING_MASK & IWL_MVM_SCAN_MASK);
        BUILD_BUG_ON(IWL_MVM_MAX_UMAC_SCANS > HWEIGHT32(IWL_MVM_SCAN_MASK) ||
                     IWL_MVM_MAX_LMAC_SCANS > HWEIGHT32(IWL_MVM_SCAN_MASK));
 
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
                mvm->max_scans = IWL_MVM_MAX_UMAC_SCANS;
        else
                mvm->max_scans = IWL_MVM_MAX_LMAC_SCANS;
@@ -524,10 +551,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
 
-               if ((mvm->fw->ucode_capa.capa[0] &
-                    IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
-                   (mvm->fw->ucode_capa.api[0] &
-                    IWL_UCODE_TLV_API_LQ_SS_PARAMS))
+               if (fw_has_capa(&mvm->fw->ucode_capa,
+                               IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
+                   fw_has_api(&mvm->fw->ucode_capa,
+                              IWL_UCODE_TLV_API_LQ_SS_PARAMS))
                        hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |=
                                IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
        }
@@ -553,30 +580,24 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                               NL80211_FEATURE_STATIC_SMPS |
                               NL80211_FEATURE_SUPPORTS_WMM_ADMISSION;
 
-       if (mvm->fw->ucode_capa.capa[0] &
-           IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT)
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT))
                hw->wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION;
-       if (mvm->fw->ucode_capa.capa[0] &
-           IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT)
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT))
                hw->wiphy->features |= NL80211_FEATURE_QUIET;
 
-       if (mvm->fw->ucode_capa.capa[0] &
-           IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
                hw->wiphy->features |=
                        NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES;
 
-       if (mvm->fw->ucode_capa.capa[0] &
-           IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
                hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
 
        mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 
-       /* currently FW API supports only one optional cipher scheme */
-       if (mvm->fw->cs[0].cipher) {
-               mvm->hw->n_cipher_schemes = 1;
-               mvm->hw->cipher_schemes = &mvm->fw->cs[0];
-       }
-
 #ifdef CONFIG_PM_SLEEP
        if (iwl_mvm_is_d0i3_supported(mvm) &&
            device_can_wakeup(mvm->trans->dev)) {
@@ -616,13 +637,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        if (ret)
                return ret;
 
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_TDLS_SUPPORT) {
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_TDLS_SUPPORT)) {
                IWL_DEBUG_TDLS(mvm, "TDLS supported\n");
                hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
        }
 
-       if (mvm->fw->ucode_capa.capa[0] &
-           IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH) {
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH)) {
                IWL_DEBUG_TDLS(mvm, "TDLS channel switch supported\n");
                hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
        }
@@ -735,6 +757,60 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
        return true;
 }
 
+#define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...)  \
+       do {                                                    \
+               if (!(le16_to_cpu(_tid_bm) & BIT(_tid)))        \
+                       break;                                  \
+               iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt); \
+       } while (0)
+
+static void
+iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                           struct ieee80211_sta *sta, u16 tid, u16 rx_ba_ssn,
+                           enum ieee80211_ampdu_mlme_action action)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_ba *ba_trig;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
+       ba_trig = (void *)trig->data;
+
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       switch (action) {
+       case IEEE80211_AMPDU_TX_OPERATIONAL: {
+               struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+               struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
+
+               CHECK_BA_TRIGGER(mvm, trig, ba_trig->tx_ba_start, tid,
+                                "TX AGG START: MAC %pM tid %d ssn %d\n",
+                                sta->addr, tid, tid_data->ssn);
+               break;
+               }
+       case IEEE80211_AMPDU_TX_STOP_CONT:
+               CHECK_BA_TRIGGER(mvm, trig, ba_trig->tx_ba_stop, tid,
+                                "TX AGG STOP: MAC %pM tid %d\n",
+                                sta->addr, tid);
+               break;
+       case IEEE80211_AMPDU_RX_START:
+               CHECK_BA_TRIGGER(mvm, trig, ba_trig->rx_ba_start, tid,
+                                "RX AGG START: MAC %pM tid %d ssn %d\n",
+                                sta->addr, tid, rx_ba_ssn);
+               break;
+       case IEEE80211_AMPDU_RX_STOP:
+               CHECK_BA_TRIGGER(mvm, trig, ba_trig->rx_ba_stop, tid,
+                                "RX AGG STOP: MAC %pM tid %d\n",
+                                sta->addr, tid);
+               break;
+       default:
+               break;
+       }
+}
+
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    enum ieee80211_ampdu_mlme_action action,
@@ -811,6 +887,16 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                ret = -EINVAL;
                break;
        }
+
+       if (!ret) {
+               u16 rx_ba_ssn = 0;
+
+               if (action == IEEE80211_AMPDU_RX_START)
+                       rx_ba_ssn = *ssn;
+
+               iwl_mvm_ampdu_check_trigger(mvm, vif, sta, tid,
+                                           rx_ba_ssn, action);
+       }
        mutex_unlock(&mvm->mutex);
 
        /*
@@ -1410,7 +1496,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
         * The work item could be running or queued if the
         * ROC time event stops just as we get here.
         */
-       cancel_work_sync(&mvm->roc_done_wk);
+       flush_work(&mvm->roc_done_wk);
 
        iwl_trans_stop_device(mvm->trans);
 
@@ -1423,20 +1509,24 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
        /*
         * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete()
         * won't be called in this case).
+        * But make sure to cleanup interfaces that have gone down before/during
+        * HW restart was requested.
         */
-       clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+       if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+               ieee80211_iterate_interfaces(mvm->hw, 0,
+                                            iwl_mvm_cleanup_iterator, mvm);
 
        /* We shouldn't have any UIDs still set.  Loop over all the UIDs to
         * make sure there's nothing left there and warn if any is found.
         */
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
                int i;
 
                for (i = 0; i < mvm->max_scans; i++) {
-                       if (WARN_ONCE(mvm->scan_uid[i],
-                                     "UMAC scan UID %d was not cleaned\n",
-                                     mvm->scan_uid[i]))
-                               mvm->scan_uid[i] = 0;
+                       if (WARN_ONCE(mvm->scan_uid_status[i],
+                                     "UMAC scan UID %d status was not cleaned\n",
+                                     i))
+                               mvm->scan_uid_status[i] = 0;
                }
        }
 
@@ -1501,7 +1591,7 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                .pwr_restriction = cpu_to_le16(8 * tx_power),
        };
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_TX_POWER_DEV))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV))
                return iwl_mvm_set_tx_power_old(mvm, vif, tx_power);
 
        if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
@@ -2360,7 +2450,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
        mutex_lock(&mvm->mutex);
 
        if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
-               iwl_mvm_scan_offload_stop(mvm, true);
+               iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
 
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
@@ -2411,12 +2501,8 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
         * cancel scan scan before ieee80211_scan_work() could run.
         * To handle that, simply return if the scan is not running.
        */
-       /* FIXME: for now, we ignore this race for UMAC scans, since
-        * they don't set the scan_status.
-        */
-       if ((mvm->scan_status & IWL_MVM_SCAN_REGULAR) ||
-           (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN))
-               iwl_mvm_cancel_scan(mvm);
+       if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
+               iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);
 
        mutex_unlock(&mvm->mutex);
 }
@@ -2765,16 +2851,12 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
         * could run.  To handle this, simply return if the scan is
         * not running.
        */
-       /* FIXME: for now, we ignore this race for UMAC scans, since
-        * they don't set the scan_status.
-        */
-       if (!(mvm->scan_status & IWL_MVM_SCAN_SCHED) &&
-           !(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
+       if (!(mvm->scan_status & IWL_MVM_SCAN_SCHED)) {
                mutex_unlock(&mvm->mutex);
                return 0;
        }
 
-       ret = iwl_mvm_scan_offload_stop(mvm, false);
+       ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, false);
        mutex_unlock(&mvm->mutex);
        iwl_mvm_wait_for_async_handlers(mvm);
 
@@ -3039,8 +3121,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
 
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
-               if (mvm->fw->ucode_capa.capa[0] &
-                   IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
+               if (fw_has_capa(&mvm->fw->ucode_capa,
+                               IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT)) {
                        /* Use aux roc framework (HS20) */
                        ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
                                                       vif, duration);
@@ -3832,7 +3914,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
        if (idx != 0)
                return -ENOENT;
 
-       if (!(mvm->fw->ucode_capa.capa[0] &
+       if (fw_has_capa(&mvm->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
                return -ENOENT;
 
@@ -3879,8 +3961,8 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
-       if (!(mvm->fw->ucode_capa.capa[0] &
-                               IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
                return;
 
        /* if beacon filtering isn't on mac80211 does it anyway */
@@ -3910,9 +3992,9 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
        mutex_unlock(&mvm->mutex);
 }
 
-static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
-                                      struct ieee80211_vif *vif,
-                                      const struct ieee80211_event *event)
+static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif,
+                                       const struct ieee80211_event *event)
 {
 #define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...)   \
        do {                                                    \
@@ -3921,7 +4003,6 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
                iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\
        } while (0)
 
-       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct iwl_fw_dbg_trigger_tlv *trig;
        struct iwl_fw_dbg_trigger_mlme *trig_mlme;
 
@@ -3965,6 +4046,75 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
 #undef CHECK_MLME_TRIGGER
 }
 
+static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm,
+                                         struct ieee80211_vif *vif,
+                                         const struct ieee80211_event *event)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_ba *ba_trig;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
+       ba_trig = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       if (!(le16_to_cpu(ba_trig->rx_bar) & BIT(event->u.ba.tid)))
+               return;
+
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                   "BAR received from %pM, tid %d, ssn %d",
+                                   event->u.ba.sta->addr, event->u.ba.tid,
+                                   event->u.ba.ssn);
+}
+
+static void
+iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif,
+                                    const struct ieee80211_event *event)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_ba *ba_trig;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
+       ba_trig = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(event->u.ba.tid)))
+               return;
+
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                   "Frame from %pM timed out, tid %d",
+                                   event->u.ba.sta->addr, event->u.ba.tid);
+}
+
+static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      const struct ieee80211_event *event)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+       switch (event->type) {
+       case MLME_EVENT:
+               iwl_mvm_event_mlme_callback(mvm, vif, event);
+               break;
+       case BAR_RX_EVENT:
+               iwl_mvm_event_bar_rx_callback(mvm, vif, event);
+               break;
+       case BA_FRAME_TIMEOUT:
+               iwl_mvm_event_frame_timeout_callback(mvm, vif, event);
+               break;
+       default:
+               break;
+       }
+}
+
 const struct ieee80211_ops iwl_mvm_hw_ops = {
        .tx = iwl_mvm_mac_tx,
        .ampdu_action = iwl_mvm_mac_ampdu_action,
index 6d332348dca631e1af0e4fec4e52e97e5fc19de4..2d4bad5fe825fb4802fc1439167323dcf4b23e7b 100644 (file)
@@ -276,6 +276,7 @@ enum iwl_mvm_ref_type {
        IWL_MVM_REF_UCODE_DOWN,
        IWL_MVM_REF_SCAN,
        IWL_MVM_REF_ROC,
+       IWL_MVM_REF_ROC_AUX,
        IWL_MVM_REF_P2P_CLIENT,
        IWL_MVM_REF_AP_IBSS,
        IWL_MVM_REF_USER,
@@ -446,6 +447,8 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
 
 extern const u8 tid_to_mac80211_ac[];
 
+#define IWL_MVM_SCAN_STOPPING_SHIFT    8
+
 enum iwl_scan_status {
        IWL_MVM_SCAN_REGULAR            = BIT(0),
        IWL_MVM_SCAN_SCHED              = BIT(1),
@@ -462,8 +465,8 @@ enum iwl_scan_status {
        IWL_MVM_SCAN_NETDETECT_MASK     = IWL_MVM_SCAN_NETDETECT |
                                          IWL_MVM_SCAN_STOPPING_NETDETECT,
 
-       IWL_MVM_SCAN_STOPPING_MASK      = 0xff00,
-       IWL_MVM_SCAN_MASK               = 0x00ff,
+       IWL_MVM_SCAN_STOPPING_MASK      = 0xff << IWL_MVM_SCAN_STOPPING_SHIFT,
+       IWL_MVM_SCAN_MASK               = 0xff,
 };
 
 /**
@@ -627,8 +630,7 @@ struct iwl_mvm {
        unsigned int max_scans;
 
        /* UMAC scan tracking */
-       u32 scan_uid[IWL_MVM_MAX_UMAC_SCANS];
-       u8 scan_seq_num, sched_scan_seq_num;
+       u32 scan_uid_status[IWL_MVM_MAX_UMAC_SCANS];
 
        /* rx chain antennas set through debugfs for the scan command */
        u8 scan_rx_ant;
@@ -818,6 +820,8 @@ struct iwl_mvm {
        } tdls_cs;
 
        struct iwl_mvm_shared_mem_cfg shared_mem_cfg;
+
+       u32 ciphers[6];
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -887,14 +891,15 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
        return mvm->trans->cfg->d0i3 &&
               mvm->trans->d0i3_mode != IWL_D0I3_MODE_OFF &&
               !iwlwifi_mod_params.d0i3_disable &&
-              (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
+              fw_has_capa(&mvm->fw->ucode_capa,
+                          IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
 }
 
 static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
 {
        bool nvm_lar = mvm->nvm_data->lar_enabled;
-       bool tlv_lar = mvm->fw->ucode_capa.capa[0] &
-               IWL_UCODE_TLV_CAPA_LAR_SUPPORT;
+       bool tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
+                                  IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
 
        if (iwlwifi_mod_params.lar_disable)
                return false;
@@ -911,24 +916,28 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
 
 static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm)
 {
-       return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE ||
-              mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC;
+       return fw_has_api(&mvm->fw->ucode_capa,
+                         IWL_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
+              fw_has_capa(&mvm->fw->ucode_capa,
+                          IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC);
 }
 
 static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm)
 {
-       return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG;
+       return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SCD_CFG);
 }
 
 static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm)
 {
-       return (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BT_COEX_PLCR) &&
+       return fw_has_capa(&mvm->fw->ucode_capa,
+                          IWL_UCODE_TLV_CAPA_BT_COEX_PLCR) &&
                IWL_MVM_BT_COEX_CORUNNING;
 }
 
 static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm)
 {
-       return (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BT_COEX_RRC) &&
+       return fw_has_capa(&mvm->fw->ucode_capa,
+                          IWL_UCODE_TLV_CAPA_BT_COEX_RRC) &&
                IWL_MVM_BT_COEX_RRC;
 }
 
@@ -1121,34 +1130,34 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                           struct cfg80211_scan_request *req,
                           struct ieee80211_scan_ies *ies);
 int iwl_mvm_scan_size(struct iwl_mvm *mvm);
-int iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
+int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify);
 int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm);
 void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
 
 /* Scheduled scan */
-int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
-                                          struct iwl_rx_cmd_buffer *rxb,
-                                          struct iwl_device_cmd *cmd);
-int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm,
-                                               struct iwl_rx_cmd_buffer *rxb,
-                                               struct iwl_device_cmd *cmd);
-int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
-                                      struct cfg80211_sched_scan_request *req);
+int iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
+                                       struct iwl_rx_cmd_buffer *rxb,
+                                       struct iwl_device_cmd *cmd);
+int iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd);
 int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
                             struct ieee80211_vif *vif,
                             struct cfg80211_sched_scan_request *req,
                             struct ieee80211_scan_ies *ies,
                             int type);
-int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
-int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
-                                   struct iwl_rx_cmd_buffer *rxb,
-                                   struct iwl_device_cmd *cmd);
+int iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm,
+                               struct iwl_rx_cmd_buffer *rxb,
+                               struct iwl_device_cmd *cmd);
 
 /* UMAC scan */
 int iwl_mvm_config_scan(struct iwl_mvm *mvm);
 int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
                                        struct iwl_rx_cmd_buffer *rxb,
                                        struct iwl_device_cmd *cmd);
+int iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd);
 
 /* MVM debugfs */
 #ifdef CONFIG_IWLWIFI_DEBUGFS
index 87b2a30a2308439c4e7a3f3bd80e419f9583af5a..2a6be350704a9442245f6e8bd2391503f67f0c6d 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -316,8 +316,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
        phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data;
 
        lar_enabled = !iwlwifi_mod_params.lar_disable &&
-                     (mvm->fw->ucode_capa.capa[0] &
-                      IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
+                     fw_has_capa(&mvm->fw->ucode_capa,
+                                 IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
 
        return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
                                  regulatory, mac_override, phy_sku,
@@ -583,9 +583,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
                kfree(nvm_buffer);
        }
 
-       /* load external NVM if configured */
+       /* Only if PNVM selected in the mod param - load external NVM  */
        if (mvm->nvm_file_name) {
-               /* read External NVM file - take the default */
+               /* read External NVM file from the mod param */
                ret = iwl_mvm_read_external_nvm(mvm);
                if (ret) {
                        /* choose the nvm_file name according to the
@@ -792,8 +792,8 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
        char mcc[3];
 
        if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
-               tlv_lar = mvm->fw->ucode_capa.capa[0] &
-                       IWL_UCODE_TLV_CAPA_LAR_SUPPORT;
+               tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
+                                     IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
                nvm_lar = mvm->nvm_data->lar_enabled;
                if (tlv_lar != nvm_lar)
                        IWL_INFO(mvm,
index 02028bcb3ff6f84c443bb8c32f8e6838e78dc222..e4fa50075ffdc3b51c66f4b6587595134da9ade3 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -194,7 +194,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
         * (PCIe power is lost before PERST# is asserted), causing ME FW
         * to lose ownership and not being able to obtain it back.
         */
-       if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+       if (!mvm->trans->cfg->apmg_not_supported)
                iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
                                       APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
                                       ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
@@ -238,13 +238,15 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
        RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false),
 
        RX_HANDLER(SCAN_ITERATION_COMPLETE,
-                  iwl_mvm_rx_scan_offload_iter_complete_notif, false),
+                  iwl_mvm_rx_lmac_scan_iter_complete_notif, false),
        RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
-                  iwl_mvm_rx_scan_offload_complete_notif, true),
-       RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
+                  iwl_mvm_rx_lmac_scan_complete_notif, true),
+       RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_match_found,
                   false),
        RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
                   true),
+       RX_HANDLER(SCAN_ITERATION_COMPLETE_UMAC,
+                  iwl_mvm_rx_umac_scan_iter_complete_notif, false),
 
        RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
 
@@ -279,11 +281,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(BINDING_CONTEXT_CMD),
        CMD(TIME_QUOTA_CMD),
        CMD(NON_QOS_TX_COUNTER_CMD),
-       CMD(SCAN_REQUEST_CMD),
-       CMD(SCAN_ABORT_CMD),
-       CMD(SCAN_START_NOTIFICATION),
-       CMD(SCAN_RESULTS_NOTIFICATION),
-       CMD(SCAN_COMPLETE_NOTIFICATION),
+       CMD(DC2DC_CONFIG_CMD),
        CMD(NVM_ACCESS_CMD),
        CMD(PHY_CONFIGURATION_CMD),
        CMD(CALIB_RES_NOTIF_PHY_DB),
@@ -356,6 +354,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION),
        CMD(TDLS_CONFIG_CMD),
        CMD(MCC_UPDATE_CMD),
+       CMD(SCAN_ITERATION_COMPLETE_UMAC),
 };
 #undef CMD
 
@@ -517,15 +516,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        min_backoff = calc_min_backoff(trans, cfg);
        iwl_mvm_tt_initialize(mvm, min_backoff);
-       /* set the nvm_file_name according to priority */
-       if (iwlwifi_mod_params.nvm_file) {
+
+       if (iwlwifi_mod_params.nvm_file)
                mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
-       } else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
-               if (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP)
-                       mvm->nvm_file_name = mvm->cfg->default_nvm_file_B_step;
-               else
-                       mvm->nvm_file_name = mvm->cfg->default_nvm_file_C_step;
-       }
+       else
+               IWL_DEBUG_EEPROM(mvm->trans->dev,
+                                "working without external nvm file\n");
 
        if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
                 "not allowing power-up and not having nvm_file\n"))
index 1295178abfae7d863fedb83e7943f084106288bc..daff1d0a8e4adad6ebf2cdc5e811411776d63913 100644 (file)
@@ -138,7 +138,7 @@ struct rs_tx_column;
 
 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
                                     struct ieee80211_sta *sta,
-                                    struct iwl_scale_tbl_info *tbl,
+                                    struct rs_rate *rate,
                                     const struct rs_tx_column *next_col);
 
 struct rs_tx_column {
@@ -150,14 +150,14 @@ struct rs_tx_column {
 };
 
 static bool rs_ant_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                        struct iwl_scale_tbl_info *tbl,
+                        struct rs_rate *rate,
                         const struct rs_tx_column *next_col)
 {
        return iwl_mvm_bt_coex_is_ant_avail(mvm, next_col->ant);
 }
 
 static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         struct iwl_scale_tbl_info *tbl,
+                         struct rs_rate *rate,
                          const struct rs_tx_column *next_col)
 {
        struct iwl_mvm_sta *mvmsta;
@@ -187,7 +187,7 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 }
 
 static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         struct iwl_scale_tbl_info *tbl,
+                         struct rs_rate *rate,
                          const struct rs_tx_column *next_col)
 {
        if (!sta->ht_cap.ht_supported)
@@ -197,10 +197,9 @@ static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 }
 
 static bool rs_sgi_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                        struct iwl_scale_tbl_info *tbl,
+                        struct rs_rate *rate,
                         const struct rs_tx_column *next_col)
 {
-       struct rs_rate *rate = &tbl->rate;
        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
        struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
 
@@ -1128,8 +1127,8 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
-       bool allow_ant_mismatch = mvm->fw->ucode_capa.api[0] &
-               IWL_UCODE_TLV_API_LQ_SS_PARAMS;
+       bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa,
+                                            IWL_UCODE_TLV_API_LQ_SS_PARAMS);
 
        /* Treat uninitialized rate scaling data same as non-existing. */
        if (!lq_sta) {
@@ -1659,7 +1658,8 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 
                for (j = 0; j < MAX_COLUMN_CHECKS; j++) {
                        allow_func = next_col->checks[j];
-                       if (allow_func && !allow_func(mvm, sta, tbl, next_col))
+                       if (allow_func && !allow_func(mvm, sta, &tbl->rate,
+                                                     next_col))
                                break;
                }
 
@@ -2714,7 +2714,7 @@ static void rs_vht_init(struct iwl_mvm *mvm,
            (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
                lq_sta->stbc_capable = true;
 
-       if ((mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BEAMFORMER) &&
            (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
            (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE))
                lq_sta->bfer_capable = true;
@@ -2998,7 +2998,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
        valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
 
        /* TODO: remove old API when min FW API hits 14 */
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) &&
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_LQ_SS_PARAMS) &&
            rs_stbc_allow(mvm, sta, lq_sta))
                rate.stbc = true;
 
@@ -3212,7 +3212,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
 
        rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
 
-       if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS)
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_LQ_SS_PARAMS))
                rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate);
 
        mvmsta = iwl_mvm_sta_from_mac80211(sta);
index d6314ddf57b5d9638fcfd2fcf6ba917bb136779f..8f1d93b7a13aa1059a4844c64f825822ee07605a 100644 (file)
@@ -570,7 +570,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
        };
        u32 temperature;
 
-       if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_STATS_V10) {
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STATS_V10)) {
                struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data;
 
                if (iwl_rx_packet_payload_len(pkt) != v10_len)
@@ -610,7 +610,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
        /* Only handle rx statistics temperature changes if async temp
         * notifications are not supported
         */
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_ASYNC_DTM))
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_ASYNC_DTM))
                iwl_mvm_tt_temp_changed(mvm, temperature);
 
        ieee80211_iterate_active_interfaces(mvm->hw,
index e50fd3fd8ab0f9d44d6ef7c5e9898bbdbb2cfcb6..5de144968723d4f2a5446f0d6f9fc0607baf2efb 100644 (file)
@@ -101,14 +101,6 @@ struct iwl_mvm_scan_params {
        } schedule[2];
 };
 
-enum iwl_umac_scan_uid_type {
-       IWL_UMAC_SCAN_UID_REG_SCAN      = BIT(0),
-       IWL_UMAC_SCAN_UID_SCHED_SCAN    = BIT(1),
-};
-
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
-                             enum iwl_umac_scan_uid_type type, bool notify);
-
 static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
 {
        if (mvm->scan_rx_ant != ANT_NONE)
@@ -168,7 +160,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
 static u16 iwl_mvm_get_active_dwell(struct iwl_mvm *mvm,
                                    enum ieee80211_band band, int n_ssids)
 {
-       if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL)
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BASIC_DWELL))
                return 10;
        if (band == IEEE80211_BAND_2GHZ)
                return 20  + 3 * (n_ssids + 1);
@@ -178,7 +170,7 @@ static u16 iwl_mvm_get_active_dwell(struct iwl_mvm *mvm,
 static u16 iwl_mvm_get_passive_dwell(struct iwl_mvm *mvm,
                                     enum ieee80211_band band)
 {
-       if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL)
+       if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_BASIC_DWELL))
                        return 110;
        return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10;
 }
@@ -213,8 +205,9 @@ static void iwl_mvm_scan_calc_dwell(struct iwl_mvm *mvm,
        params->max_out_time = 120;
 
        if (iwl_mvm_low_latency(mvm)) {
-               if (mvm->fw->ucode_capa.api[0] &
-                   IWL_UCODE_TLV_API_FRAGMENTED_SCAN) {
+               if (fw_has_api(&mvm->fw->ucode_capa,
+                              IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
+
                        params->suspend_time = 105;
                        /*
                         * If there is more than one active interface make
@@ -228,8 +221,9 @@ static void iwl_mvm_scan_calc_dwell(struct iwl_mvm *mvm,
                }
        }
 
-       if (frag_passive_dwell && (mvm->fw->ucode_capa.api[0] &
-                                  IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
+       if (frag_passive_dwell &&
+           fw_has_api(&mvm->fw->ucode_capa,
+                      IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
                /*
                 * P2P device scan should not be fragmented to avoid negative
                 * impact on P2P device discovery. Configure max_out_time to be
@@ -281,8 +275,8 @@ not_bound:
 static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
 {
        /* require rrm scan whenever the fw supports it */
-       return mvm->fw->ucode_capa.capa[0] &
-              IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT;
+       return fw_has_capa(&mvm->fw->ucode_capa,
+                          IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT);
 }
 
 static int iwl_mvm_max_scan_ie_fw_cmd_room(struct iwl_mvm *mvm)
@@ -318,22 +312,41 @@ int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm)
        return max_ie_len;
 }
 
-int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm,
-                                               struct iwl_rx_cmd_buffer *rxb,
-                                               struct iwl_device_cmd *cmd)
+static u8 *iwl_mvm_dump_channel_list(struct iwl_scan_results_notif *res,
+                                    int num_res, u8 *buf, size_t buf_size)
+{
+       int i;
+       u8 *pos = buf, *end = buf + buf_size;
+
+       for (i = 0; pos < end && i < num_res; i++)
+               pos += snprintf(pos, end - pos, " %u", res[i].channel);
+
+       /* terminate the string in case the buffer was too short */
+       *(buf + buf_size - 1) = '\0';
+
+       return buf;
+}
+
+int iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_lmac_scan_complete_notif *notif = (void *)pkt->data;
+       u8 buf[256];
 
        IWL_DEBUG_SCAN(mvm,
-                      "Scan offload iteration complete: status=0x%x scanned channels=%d\n",
-                      notif->status, notif->scanned_channels);
+                      "Scan offload iteration complete: status=0x%x scanned channels=%d channels list: %s\n",
+                      notif->status, notif->scanned_channels,
+                      iwl_mvm_dump_channel_list(notif->results,
+                                                notif->scanned_channels, buf,
+                                                sizeof(buf)));
        return 0;
 }
 
-int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
-                                   struct iwl_rx_cmd_buffer *rxb,
-                                   struct iwl_device_cmd *cmd)
+int iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm,
+                               struct iwl_rx_cmd_buffer *rxb,
+                               struct iwl_device_cmd *cmd)
 {
        IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
        ieee80211_sched_scan_results(mvm->hw);
@@ -341,14 +354,27 @@ int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
        return 0;
 }
 
-int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
-                                          struct iwl_rx_cmd_buffer *rxb,
-                                          struct iwl_device_cmd *cmd)
+static const char *iwl_mvm_ebs_status_str(enum iwl_scan_ebs_status status)
+{
+       switch (status) {
+       case IWL_SCAN_EBS_SUCCESS:
+               return "successful";
+       case IWL_SCAN_EBS_INACTIVE:
+               return "inactive";
+       case IWL_SCAN_EBS_FAILED:
+       case IWL_SCAN_EBS_CHAN_NOT_FOUND:
+       default:
+               return "failed";
+       }
+}
+
+int iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
+                                       struct iwl_rx_cmd_buffer *rxb,
+                                       struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_periodic_scan_complete *scan_notif = (void *)pkt->data;
        bool aborted = (scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
-       bool ebs_successful = (scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS);
 
        /* scan status must be locked for proper checking */
        lockdep_assert_held(&mvm->mutex);
@@ -368,13 +394,13 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
 
                IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",
                               aborted ? "aborted" : "completed",
-                              ebs_successful ? "successful" : "failed");
+                              iwl_mvm_ebs_status_str(scan_notif->ebs_status));
 
                mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_SCHED;
        } else if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR) {
                IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s\n",
                               aborted ? "aborted" : "completed",
-                              ebs_successful ? "successful" : "failed");
+                              iwl_mvm_ebs_status_str(scan_notif->ebs_status));
 
                mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_REGULAR;
        } else if (mvm->scan_status & IWL_MVM_SCAN_SCHED) {
@@ -382,14 +408,14 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
 
                IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s (FW)\n",
                               aborted ? "aborted" : "completed",
-                              ebs_successful ? "successful" : "failed");
+                              iwl_mvm_ebs_status_str(scan_notif->ebs_status));
 
                mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
                ieee80211_sched_scan_stopped(mvm->hw);
        } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
                IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
                               aborted ? "aborted" : "completed",
-                              ebs_successful ? "successful" : "failed");
+                              iwl_mvm_ebs_status_str(scan_notif->ebs_status));
 
                mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
                ieee80211_scan_completed(mvm->hw,
@@ -397,7 +423,9 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
        }
 
-       mvm->last_ebs_successful = ebs_successful;
+       mvm->last_ebs_successful =
+                       scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS ||
+                       scan_notif->ebs_status == IWL_SCAN_EBS_INACTIVE;
 
        return 0;
 }
@@ -463,8 +491,9 @@ static void iwl_scan_build_ssids(struct iwl_mvm_scan_params *params,
        }
 }
 
-int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
-                                      struct cfg80211_sched_scan_request *req)
+static int
+iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
+                                  struct cfg80211_sched_scan_request *req)
 {
        struct iwl_scan_offload_profile *profile;
        struct iwl_scan_offload_profile_cfg *profile_cfg;
@@ -545,7 +574,7 @@ static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,
        return true;
 }
 
-static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
+static int iwl_mvm_lmac_scan_abort(struct iwl_mvm *mvm)
 {
        int ret;
        struct iwl_host_cmd cmd = {
@@ -553,12 +582,6 @@ static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
        };
        u32 status;
 
-       /* Exit instantly with error when device is not ready
-        * to receive scan abort command or it does not perform
-        * scheduled scan currently */
-       if (!mvm->scan_status)
-               return -EIO;
-
        ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
        if (ret)
                return ret;
@@ -578,73 +601,6 @@ static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
        return ret;
 }
 
-int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
-{
-       int ret;
-       struct iwl_notification_wait wait_scan_done;
-       static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
-       bool sched = !!(mvm->scan_status & IWL_MVM_SCAN_SCHED);
-
-       lockdep_assert_held(&mvm->mutex);
-
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-               return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
-                                         notify);
-
-       /* FIXME: For now we only check if no scan is set here, since
-        * we only support LMAC in this flow and it doesn't support
-        * multiple scans.
-        */
-       if (!mvm->scan_status)
-               return 0;
-
-       if (iwl_mvm_is_radio_killed(mvm)) {
-               ret = 0;
-               goto out;
-       }
-
-       iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
-                                  scan_done_notif,
-                                  ARRAY_SIZE(scan_done_notif),
-                                  NULL, NULL);
-
-       ret = iwl_mvm_send_scan_offload_abort(mvm);
-       if (ret) {
-               IWL_DEBUG_SCAN(mvm, "Send stop %sscan failed %d\n",
-                              sched ? "offloaded " : "", ret);
-               iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
-               goto out;
-       }
-
-       IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
-                      sched ? "scheduled " : "");
-
-       ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
-out:
-       /* Clear the scan status so the next scan requests will
-        * succeed and mark the scan as stopping, so that the Rx
-        * handler doesn't do anything, as the scan was stopped from
-        * above. Since the rx handler won't do anything now, we have
-        * to release the scan reference here.
-        */
-       if (mvm->scan_status == IWL_MVM_SCAN_REGULAR)
-               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-
-       if (sched) {
-               mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
-               mvm->scan_status |= IWL_MVM_SCAN_STOPPING_SCHED;
-               if (notify)
-                       ieee80211_sched_scan_stopped(mvm->hw);
-       } else {
-               mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
-               mvm->scan_status |= IWL_MVM_SCAN_STOPPING_REGULAR;
-               if (notify)
-                       ieee80211_scan_completed(mvm->hw, true);
-       }
-
-       return ret;
-}
-
 static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm,
                                     struct iwl_scan_req_tx_cmd *tx_cmd,
                                     bool no_cck)
@@ -775,6 +731,22 @@ iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        params->preq.common_data.len = cpu_to_le16(ies->common_ie_len);
 }
 
+static __le32 iwl_mvm_scan_priority(struct iwl_mvm *mvm,
+                                   enum iwl_scan_priority_ext prio)
+{
+       if (fw_has_api(&mvm->fw->ucode_capa,
+                      IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY))
+               return cpu_to_le32(prio);
+
+       if (prio <= IWL_SCAN_PRIORITY_EXT_2)
+               return cpu_to_le32(IWL_SCAN_PRIORITY_LOW);
+
+       if (prio <= IWL_SCAN_PRIORITY_EXT_4)
+               return cpu_to_le32(IWL_SCAN_PRIORITY_MEDIUM);
+
+       return cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+}
+
 static void iwl_mvm_scan_lmac_dwell(struct iwl_mvm *mvm,
                                    struct iwl_scan_req_lmac *cmd,
                                    struct iwl_mvm_scan_params *params)
@@ -786,7 +758,7 @@ static void iwl_mvm_scan_lmac_dwell(struct iwl_mvm *mvm,
                                params->dwell[IEEE80211_BAND_2GHZ].fragmented;
        cmd->max_out_time = cpu_to_le32(params->max_out_time);
        cmd->suspend_time = cpu_to_le32(params->suspend_time);
-       cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+       cmd->scan_prio = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
 }
 
 static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
@@ -801,19 +773,23 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
                 iwl_mvm_max_scan_ie_fw_cmd_room(mvm)));
 }
 
-static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, int n_iterations)
+static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif,
+                                       int n_iterations)
 {
        const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;
 
        /* We can only use EBS if:
         *      1. the feature is supported;
         *      2. the last EBS was successful;
-        *      3. if only single scan, the single scan EBS API is supported.
+        *      3. if only single scan, the single scan EBS API is supported;
+        *      4. it's not a p2p find operation.
         */
        return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
                mvm->last_ebs_successful &&
                (n_iterations > 1 ||
-                (capa->api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)));
+                fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) &&
+               vif->type != NL80211_IFTYPE_P2P_DEVICE);
 }
 
 static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params)
@@ -891,7 +867,7 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        cmd->schedule[1].iterations = params->schedule[1].iterations;
        cmd->schedule[1].full_scan_mul = params->schedule[1].iterations;
 
-       if (iwl_mvm_scan_use_ebs(mvm, n_iterations)) {
+       if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) {
                cmd->channel_opt[0].flags =
                        cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
                                    IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
@@ -914,32 +890,6 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        return 0;
 }
 
-int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
-{
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-               return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_REG_SCAN,
-                                         true);
-
-       if (!(mvm->scan_status & IWL_MVM_SCAN_REGULAR))
-               return 0;
-
-       if (iwl_mvm_is_radio_killed(mvm)) {
-               ieee80211_scan_completed(mvm->hw, true);
-               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-               mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
-               return 0;
-       }
-
-       return iwl_mvm_scan_offload_stop(mvm, true);
-}
-
-/* UMAC scan API */
-
-struct iwl_umac_scan_done {
-       struct iwl_mvm *mvm;
-       enum iwl_umac_scan_uid_type type;
-};
-
 static int rate_to_scan_rate_flag(unsigned int rate)
 {
        static const int rate_to_scan_rate[IWL_RATE_COUNT] = {
@@ -1048,68 +998,15 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
        return ret;
 }
 
-static int iwl_mvm_find_scan_uid(struct iwl_mvm *mvm, u32 uid)
+static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
 {
        int i;
 
        for (i = 0; i < mvm->max_scans; i++)
-               if (mvm->scan_uid[i] == uid)
+               if (mvm->scan_uid_status[i] == status)
                        return i;
 
-       return i;
-}
-
-static int iwl_mvm_find_free_scan_uid(struct iwl_mvm *mvm)
-{
-       return iwl_mvm_find_scan_uid(mvm, 0);
-}
-
-static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
-                                  enum iwl_umac_scan_uid_type type)
-{
-       int i;
-
-       for (i = 0; i < mvm->max_scans; i++)
-               if (mvm->scan_uid[i] & type)
-                       return true;
-
-       return false;
-}
-
-static int iwl_mvm_find_first_scan(struct iwl_mvm *mvm,
-                                  enum iwl_umac_scan_uid_type type)
-{
-       int i;
-
-       for (i = 0; i < mvm->max_scans; i++)
-               if (mvm->scan_uid[i] & type)
-                       return i;
-
-       return i;
-}
-
-static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
-                                enum iwl_umac_scan_uid_type type)
-{
-       u32 uid;
-
-       /* make sure exactly one bit is on in scan type */
-       WARN_ON(hweight8(type) != 1);
-
-       /*
-        * Make sure scan uids are unique. If one scan lasts long time while
-        * others are completing frequently, the seq number will wrap up and
-        * we may have more than one scan with the same uid.
-        */
-       do {
-               uid = type | (mvm->scan_seq_num <<
-                             IWL_UMAC_SCAN_UID_SEQ_OFFSET);
-               mvm->scan_seq_num++;
-       } while (iwl_mvm_find_scan_uid(mvm, uid) < mvm->max_scans);
-
-       IWL_DEBUG_SCAN(mvm, "Generated scan UID %u\n", uid);
-
-       return uid;
+       return -ENOENT;
 }
 
 static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
@@ -1123,12 +1020,15 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
                                params->dwell[IEEE80211_BAND_2GHZ].fragmented;
        cmd->max_out_time = cpu_to_le32(params->max_out_time);
        cmd->suspend_time = cpu_to_le32(params->suspend_time);
-       cmd->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+       cmd->scan_priority =
+               iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
 
        if (iwl_mvm_scan_total_iterations(params) == 0)
-               cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+               cmd->ooc_priority =
+                       iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
        else
-               cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_LOW);
+               cmd->ooc_priority =
+                       iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_2);
 }
 
 static void
@@ -1173,26 +1073,30 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
        if (iwl_mvm_scan_total_iterations(params) > 1)
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+       if (mvm->scan_iter_notif_enabled)
+               flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
+#endif
        return flags;
 }
 
 static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-                            struct iwl_mvm_scan_params *params)
+                            struct iwl_mvm_scan_params *params,
+                            int type)
 {
        struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
        struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
                sizeof(struct iwl_scan_channel_cfg_umac) *
                        mvm->fw->ucode_capa.n_scan_channels;
-       u32 uid;
+       int uid;
        u32 ssid_bitmap = 0;
        int n_iterations = iwl_mvm_scan_total_iterations(params);
-       int uid_idx;
 
        lockdep_assert_held(&mvm->mutex);
 
-       uid_idx = iwl_mvm_find_free_scan_uid(mvm);
-       if (uid_idx >= mvm->max_scans)
-               return -EBUSY;
+       uid = iwl_mvm_scan_uid_by_status(mvm, 0);
+       if (uid < 0)
+               return uid;
 
        memset(cmd, 0, ksize(cmd));
        cmd->hdr.size = cpu_to_le16(iwl_mvm_scan_size(mvm) -
@@ -1200,17 +1104,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        iwl_mvm_scan_umac_dwell(mvm, cmd, params);
 
-       if (n_iterations == 1)
-               uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
-       else
-               uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN);
+       mvm->scan_uid_status[uid] = type;
 
-       mvm->scan_uid[uid_idx] = uid;
        cmd->uid = cpu_to_le32(uid);
-
        cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params));
 
-       if (iwl_mvm_scan_use_ebs(mvm, n_iterations))
+       if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations))
                cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
                                     IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
                                     IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
@@ -1222,8 +1121,8 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
                                       params->n_channels, ssid_bitmap, cmd);
 
-       /* With UMAC we can have only one schedule, so use the sum of
-        * the iterations (with a a maximum of 255).
+       /* With UMAC we use only one schedule for now, so use the sum
+        * of the iterations (with a a maximum of 255).
         */
        sec_part->schedule[0].iter_count =
                (n_iterations > 255) ? 255 : n_iterations;
@@ -1262,11 +1161,11 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type)
        case IWL_MVM_SCAN_REGULAR:
                if (mvm->scan_status & IWL_MVM_SCAN_REGULAR_MASK)
                        return -EBUSY;
-               return iwl_mvm_scan_offload_stop(mvm, true);
+               return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);
        case IWL_MVM_SCAN_SCHED:
                if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK)
                        return -EBUSY;
-               return iwl_mvm_cancel_scan(mvm);
+               iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);
        case IWL_MVM_SCAN_NETDETECT:
                /* No need to stop anything for net-detect since the
                 * firmware is restarted anyway.  This way, any sched
@@ -1337,9 +1236,10 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
 
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
                hcmd.id = SCAN_REQ_UMAC;
-               ret = iwl_mvm_scan_umac(mvm, vif, &params);
+               ret = iwl_mvm_scan_umac(mvm, vif, &params,
+                                       IWL_MVM_SCAN_REGULAR);
        } else {
                hcmd.id = SCAN_OFFLOAD_REQUEST_CMD;
                ret = iwl_mvm_scan_lmac(mvm, vif, &params);
@@ -1444,9 +1344,9 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
 
        iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
 
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
                hcmd.id = SCAN_REQ_UMAC;
-               ret = iwl_mvm_scan_umac(mvm, vif, &params);
+               ret = iwl_mvm_scan_umac(mvm, vif, &params, IWL_MVM_SCAN_SCHED);
        } else {
                hcmd.id = SCAN_OFFLOAD_REQUEST_CMD;
                ret = iwl_mvm_scan_lmac(mvm, vif, &params);
@@ -1478,144 +1378,118 @@ int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_umac_scan_complete *notif = (void *)pkt->data;
        u32 uid = __le32_to_cpu(notif->uid);
-       bool sched = !!(uid & IWL_UMAC_SCAN_UID_SCHED_SCAN);
-       int uid_idx = iwl_mvm_find_scan_uid(mvm, uid);
+       bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED);
 
-       /*
-        * Scan uid may be set to zero in case of scan abort request from above.
-        */
-       if (uid_idx >= mvm->max_scans)
+       if (WARN_ON(!(mvm->scan_uid_status[uid] & mvm->scan_status)))
                return 0;
 
+       /* if the scan is already stopping, we don't need to notify mac80211 */
+       if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
+               ieee80211_scan_completed(mvm->hw, aborted);
+               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+       } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
+               ieee80211_sched_scan_stopped(mvm->hw);
+       }
+
+       mvm->scan_status &= ~mvm->scan_uid_status[uid];
+
        IWL_DEBUG_SCAN(mvm,
-                      "Scan completed, uid %u type %s, status %s, EBS status %s\n",
-                      uid, sched ? "sched" : "regular",
+                      "Scan completed, uid %u type %u, status %s, EBS status %s\n",
+                      uid, mvm->scan_uid_status[uid],
                       notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
                                "completed" : "aborted",
-                      notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
-                               "success" : "failed");
+                      iwl_mvm_ebs_status_str(notif->ebs_status));
 
-       if (notif->ebs_status)
+       if (notif->ebs_status != IWL_SCAN_EBS_SUCCESS &&
+           notif->ebs_status != IWL_SCAN_EBS_INACTIVE)
                mvm->last_ebs_successful = false;
 
-       mvm->scan_uid[uid_idx] = 0;
-
-       if (!sched) {
-               ieee80211_scan_completed(mvm->hw,
-                                        notif->status ==
-                                               IWL_SCAN_OFFLOAD_ABORTED);
-               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-       } else if (!iwl_mvm_find_scan_type(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN)) {
-               ieee80211_sched_scan_stopped(mvm->hw);
-       } else {
-               IWL_DEBUG_SCAN(mvm, "Another sched scan is running\n");
-       }
+       mvm->scan_uid_status[uid] = 0;
 
        return 0;
 }
 
-static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait,
-                                    struct iwl_rx_packet *pkt, void *data)
+int iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+                                            struct iwl_rx_cmd_buffer *rxb,
+                                            struct iwl_device_cmd *cmd)
 {
-       struct iwl_umac_scan_done *scan_done = data;
-       struct iwl_umac_scan_complete *notif = (void *)pkt->data;
-       u32 uid = __le32_to_cpu(notif->uid);
-       int uid_idx = iwl_mvm_find_scan_uid(scan_done->mvm, uid);
-
-       if (WARN_ON(pkt->hdr.cmd != SCAN_COMPLETE_UMAC))
-               return false;
-
-       if (uid_idx >= scan_done->mvm->max_scans)
-               return false;
-
-       /*
-        * Clear scan uid of scans that was aborted from above and completed
-        * in FW so the RX handler does nothing. Set last_ebs_successful here if
-        * needed.
-        */
-       scan_done->mvm->scan_uid[uid_idx] = 0;
-
-       if (notif->ebs_status)
-               scan_done->mvm->last_ebs_successful = false;
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
+       u8 buf[256];
 
-       return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type);
+       IWL_DEBUG_SCAN(mvm,
+                      "UMAC Scan iteration complete: status=0x%x scanned_channels=%d channels list: %s\n",
+                      notif->status, notif->scanned_channels,
+                      iwl_mvm_dump_channel_list(notif->results,
+                                                notif->scanned_channels, buf,
+                                                sizeof(buf)));
+       return 0;
 }
 
-static int iwl_umac_scan_abort_one(struct iwl_mvm *mvm, u32 uid)
+static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
 {
        struct iwl_umac_scan_abort cmd = {
                .hdr.size = cpu_to_le16(sizeof(struct iwl_umac_scan_abort) -
                                        sizeof(struct iwl_mvm_umac_cmd_hdr)),
-               .uid = cpu_to_le32(uid),
        };
+       int uid, ret;
 
        lockdep_assert_held(&mvm->mutex);
 
+       /* We should always get a valid index here, because we already
+        * checked that this type of scan was running in the generic
+        * code.
+        */
+       uid = iwl_mvm_scan_uid_by_status(mvm, type);
+       if (WARN_ON_ONCE(uid < 0))
+               return uid;
+
+       cmd.uid = cpu_to_le32(uid);
+
        IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);
 
-       return iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_UMAC, 0, sizeof(cmd), &cmd);
+       ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_UMAC, 0, sizeof(cmd), &cmd);
+       if (!ret)
+               mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT;
+
+       return ret;
 }
 
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
-                             enum iwl_umac_scan_uid_type type, bool notify)
+static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
 {
        struct iwl_notification_wait wait_scan_done;
-       static const u8 scan_done_notif[] = { SCAN_COMPLETE_UMAC, };
-       struct iwl_umac_scan_done scan_done = {
-               .mvm = mvm,
-               .type = type,
-       };
-       int i, ret = -EIO;
+       static const u8 scan_done_notif[] = { SCAN_COMPLETE_UMAC,
+                                             SCAN_OFFLOAD_COMPLETE, };
+       int ret;
+
+       lockdep_assert_held(&mvm->mutex);
 
        iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
                                   scan_done_notif,
                                   ARRAY_SIZE(scan_done_notif),
-                                  iwl_scan_umac_done_check, &scan_done);
+                                  NULL, NULL);
 
        IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);
 
-       for (i = 0; i < mvm->max_scans; i++) {
-               if (mvm->scan_uid[i] & type) {
-                       int err;
-
-                       if (iwl_mvm_is_radio_killed(mvm) &&
-                           (type & IWL_UMAC_SCAN_UID_REG_SCAN)) {
-                               ieee80211_scan_completed(mvm->hw, true);
-                               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-                               break;
-                       }
-
-                       err = iwl_umac_scan_abort_one(mvm, mvm->scan_uid[i]);
-                       if (!err)
-                               ret = 0;
-               }
-       }
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
+               ret = iwl_mvm_umac_scan_abort(mvm, type);
+       else
+               ret = iwl_mvm_lmac_scan_abort(mvm);
 
        if (ret) {
-               IWL_DEBUG_SCAN(mvm, "Couldn't stop scan\n");
+               IWL_DEBUG_SCAN(mvm, "couldn't stop scan type %d\n", type);
                iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
                return ret;
        }
 
        ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
-       if (ret)
-               return ret;
-
-       if (notify) {
-               if (type & IWL_UMAC_SCAN_UID_SCHED_SCAN)
-                       ieee80211_sched_scan_stopped(mvm->hw);
-               if (type & IWL_UMAC_SCAN_UID_REG_SCAN) {
-                       ieee80211_scan_completed(mvm->hw, true);
-                       iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-               }
-       }
 
        return ret;
 }
 
 int iwl_mvm_scan_size(struct iwl_mvm *mvm)
 {
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
                return sizeof(struct iwl_scan_req_umac) +
                        sizeof(struct iwl_scan_channel_cfg_umac) *
                                mvm->fw->ucode_capa.n_scan_channels +
@@ -1633,19 +1507,18 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
  */
 void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
 {
-       if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
-               u32 uid, i;
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
+               int uid, i;
 
-               uid = iwl_mvm_find_first_scan(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
-               if (uid < mvm->max_scans) {
+               uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);
+               if (uid >= 0) {
                        ieee80211_scan_completed(mvm->hw, true);
-                       mvm->scan_uid[uid] = 0;
+                       mvm->scan_uid_status[uid] = 0;
                }
-               uid = iwl_mvm_find_first_scan(mvm,
-                                             IWL_UMAC_SCAN_UID_SCHED_SCAN);
-               if (uid < mvm->max_scans && !mvm->restart_fw) {
+               uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
+               if (uid >= 0 && !mvm->restart_fw) {
                        ieee80211_sched_scan_stopped(mvm->hw);
-                       mvm->scan_uid[uid] = 0;
+                       mvm->scan_uid_status[uid] = 0;
                }
 
                /* We shouldn't have any UIDs still set.  Loop over all the
@@ -1653,10 +1526,10 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
                 * any is found.
                 */
                for (i = 0; i < mvm->max_scans; i++) {
-                       if (WARN_ONCE(mvm->scan_uid[i],
-                                     "UMAC scan UID %d was not cleaned\n",
-                                     mvm->scan_uid[i]))
-                               mvm->scan_uid[i] = 0;
+                       if (WARN_ONCE(mvm->scan_uid_status[i],
+                                     "UMAC scan UID %d status was not cleaned\n",
+                                     i))
+                               mvm->scan_uid_status[i] = 0;
                }
        } else {
                if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
@@ -1670,3 +1543,40 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
                        ieee80211_sched_scan_stopped(mvm->hw);
        }
 }
+
+int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
+{
+       int ret;
+
+       if (!(mvm->scan_status & type))
+               return 0;
+
+       if (iwl_mvm_is_radio_killed(mvm)) {
+               ret = 0;
+               goto out;
+       }
+
+       ret = iwl_mvm_scan_stop_wait(mvm, type);
+       if (!ret)
+               mvm->scan_status |= type << IWL_MVM_SCAN_STOPPING_SHIFT;
+out:
+       /* Clear the scan status so the next scan requests will
+        * succeed and mark the scan as stopping, so that the Rx
+        * handler doesn't do anything, as the scan was stopped from
+        * above.
+        */
+       mvm->scan_status &= ~type;
+
+       if (type == IWL_MVM_SCAN_REGULAR) {
+               /* Since the rx handler won't do anything now, we have
+                * to release the scan reference here.
+                */
+               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+               if (notify)
+                       ieee80211_scan_completed(mvm->hw, true);
+       } else if (notify) {
+               ieee80211_sched_scan_stopped(mvm->hw);
+       }
+
+       return ret;
+}
index 1845b79487c81b446e0432bc385e9fc12884ff68..d68dc697a4a06ef2b9c786de0fc98f3e5fe35544 100644 (file)
@@ -5,8 +5,8 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -31,8 +31,8 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1000,13 +1000,13 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
 
+       iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid,
+                              buf_size, ssn, wdg_timeout);
+
        ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
        if (ret)
                return -EIO;
 
-       iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid,
-                              buf_size, ssn, wdg_timeout);
-
        /*
         * Even though in theory the peer could have different
         * aggregation reorder buffer sizes for different sessions,
index fd7b0d36f9a620b8e99dcc7b643806b76f09af4d..d24b6a83e68cfcd4281301c907cb62a24661da96 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,12 +108,14 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
         * in the case that the time event actually completed in the firmware
         * (which is handled in iwl_mvm_te_handle_notif).
         */
-       if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
+       if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) {
                queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
-       if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
+               iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
+       }
+       if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) {
                queues |= BIT(mvm->aux_queue);
-
-       iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
+               iwl_mvm_unref(mvm, IWL_MVM_REF_ROC_AUX);
+       }
 
        synchronize_net();
 
@@ -393,6 +395,7 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
        } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
                set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
                te_data->running = true;
+               iwl_mvm_ref(mvm, IWL_MVM_REF_ROC_AUX);
                ieee80211_ready_on_channel(mvm->hw); /* Start TE */
        } else {
                IWL_DEBUG_TE(mvm,
@@ -794,13 +797,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
 {
-       struct iwl_mvm_vif *mvmvif;
+       struct iwl_mvm_vif *mvmvif = NULL;
        struct iwl_mvm_time_event_data *te_data;
        bool is_p2p = false;
 
        lockdep_assert_held(&mvm->mutex);
 
-       mvmvif = NULL;
        spin_lock_bh(&mvm->time_event_lock);
 
        /*
@@ -818,17 +820,14 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
                }
        }
 
-       /*
-        * Iterate over the list of aux roc time events and find the time
-        * event that is associated with a BSS interface.
-        * This assumes that a BSS interface can have only a single time
-        * event at any given time and this time event corresponds to a ROC
-        * request
+       /* There can only be at most one AUX ROC time event, we just use the
+        * list to simplify/unify code. Remove it if it exists.
         */
-       list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
+       te_data = list_first_entry_or_null(&mvm->aux_roc_te_list,
+                                          struct iwl_mvm_time_event_data,
+                                          list);
+       if (te_data)
                mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
-               goto remove_te;
-       }
 
 remove_te:
        spin_unlock_bh(&mvm->time_event_lock);
index ef32e177f662b3ba03772e02b1c9b9e512bcd64f..7ba7a118ff5ca28615f5ceeb745f577999ea52dc 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "mvm.h"
 #include "sta.h"
 
+static void
+iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
+                         u16 tid, u16 ssn)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_ba *ba_trig;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
+       ba_trig = (void *)trig->data;
+
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, NULL, trig))
+               return;
+
+       if (!(le16_to_cpu(ba_trig->tx_bar) & BIT(tid)))
+               return;
+
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                   "BAR sent to %pM, tid %d, ssn %d",
+                                   addr, tid, ssn);
+}
+
 /*
  * Sets most of the Tx cmd's fields
  */
@@ -101,12 +125,15 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
        } else if (ieee80211_is_back_req(fc)) {
                struct ieee80211_bar *bar = (void *)skb->data;
                u16 control = le16_to_cpu(bar->control);
+               u16 ssn = le16_to_cpu(bar->start_seq_num);
 
                tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
                tx_cmd->tid_tspec = (control &
                                     IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
                        IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
                WARN_ON_ONCE(tx_cmd->tid_tspec >= IWL_MAX_TID_COUNT);
+               iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd->tid_tspec,
+                                         ssn);
        } else {
                tx_cmd->tid_tspec = IWL_TID_NON_QOS;
                if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
@@ -144,8 +171,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
            !is_multicast_ether_addr(ieee80211_get_DA(hdr)))
                tx_flags |= TX_CMD_FLG_PROT_REQUIRE;
 
-       if ((mvm->fw->ucode_capa.capa[0] &
-            IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT) &&
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT) &&
            ieee80211_action_contains_tpc(skb))
                tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
 
index bc55a8b82db6d88ad42ef1151e0c5c53c2cbf64c..03f8e06dded72fc74a302c7e52fced302631dc01 100644 (file)
@@ -584,7 +584,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
        struct iwl_error_event_table table;
        u32 base;
 
-       if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_NEW_VERSION)) {
+       if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION)) {
                iwl_mvm_dump_nic_error_log_old(mvm);
                return;
        }
index b1856973492237dcbee2ebf640ebeb0bf593fecb..2ed1e4d2774da83f1cd609983c8383c48d37a128 100644 (file)
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * 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
@@ -32,7 +32,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -629,7 +629,18 @@ static int iwl_pci_resume(struct device *device)
        if (!trans->op_mode)
                return 0;
 
-       iwl_enable_rfkill_int(trans);
+       /*
+        * On suspend, ict is disabled, and the interrupt mask
+        * gets cleared. Reconfigure them both in case of d0i3
+        * image. Otherwise, only enable rfkill interrupt (in
+        * order to keep track of the rfkill status)
+        */
+       if (trans->wowlan_d0i3) {
+               iwl_pcie_reset_ict(trans);
+               iwl_enable_interrupts(trans);
+       } else {
+               iwl_enable_rfkill_int(trans);
+       }
 
        hw_rfkill = iwl_is_rfkill_set(trans);
        iwl_trans_pcie_rf_kill(trans, hw_rfkill);
index 376b84e54ad7e8bbb48d039d354c03748665451c..31f72a61cc3fe06b6d9189f718cc3315677625ad 100644 (file)
 #include "iwl-io.h"
 #include "iwl-op-mode.h"
 
+/*
+ * RX related structures and functions
+ */
+#define RX_NUM_QUEUES 1
+#define RX_POST_REQ_ALLOC 2
+#define RX_CLAIM_REQ_ALLOC 8
+#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES)
+#define RX_LOW_WATERMARK 8
+
 struct iwl_host_cmd;
 
 /*This file includes the declaration that are internal to the
@@ -77,29 +86,29 @@ struct isr_statistics {
  * struct iwl_rxq - 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
+ * @used_count: Number of RBDs handled to allocator to use for allocation
  * @write_actual:
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
+ * @rx_free: list of RBDs with allocated RB ready for use
+ * @rx_used: list of RBDs with no RB attached
  * @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:
+ * @pool: initial pool of iwl_rx_mem_buffer for the queue
+ * @queue: actual rx queue
  *
  * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
  */
 struct iwl_rxq {
        __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 used_count;
        u32 write_actual;
        struct list_head rx_free;
        struct list_head rx_used;
@@ -107,6 +116,32 @@ struct iwl_rxq {
        struct iwl_rb_status *rb_stts;
        dma_addr_t rb_stts_dma;
        spinlock_t lock;
+       struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE];
+       struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+};
+
+/**
+ * struct iwl_rb_allocator - Rx allocator
+ * @pool: initial pool of allocator
+ * @req_pending: number of requests the allcator had not processed yet
+ * @req_ready: number of requests honored and ready for claiming
+ * @rbd_allocated: RBDs with pages allocated and ready to be handled to
+ *     the queue. This is a list of &struct iwl_rx_mem_buffer
+ * @rbd_empty: RBDs with no page attached for allocator use. This is a list
+ *     of &struct iwl_rx_mem_buffer
+ * @lock: protects the rbd_allocated and rbd_empty lists
+ * @alloc_wq: work queue for background calls
+ * @rx_alloc: work struct for background calls
+ */
+struct iwl_rb_allocator {
+       struct iwl_rx_mem_buffer pool[RX_POOL_SIZE];
+       atomic_t req_pending;
+       atomic_t req_ready;
+       struct list_head rbd_allocated;
+       struct list_head rbd_empty;
+       spinlock_t lock;
+       struct workqueue_struct *alloc_wq;
+       struct work_struct rx_alloc;
 };
 
 struct iwl_dma_ptr {
@@ -250,7 +285,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
 /**
  * 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
+ * @rba: allocator for RX replenishing
  * @drv - pointer to iwl_drv
  * @trans: pointer to the generic transport area
  * @scd_base_addr: scheduler sram base address in SRAM
@@ -273,7 +308,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
  */
 struct iwl_trans_pcie {
        struct iwl_rxq rxq;
-       struct work_struct rx_replenish;
+       struct iwl_rb_allocator rba;
        struct iwl_trans *trans;
        struct iwl_drv *drv;
 
index 7ff69c642103f1febeea67d9c082a035039b4121..a3fbaa0ef5e04de7d1032c79ca35e82364dac7ea 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
  * resets the Rx queue buffers with new memory.
  *
  * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->rxq is replenished and the READ INDEX is updated (updating the
- *   'processed' and 'read' driver indexes as well)
+ * + A list of pre-allocated RBDs is stored in iwl->rxq->rx_free.
+ *   When the interrupt handler is called, the request is processed.
+ *   The page is either stolen - transferred to the upper layer
+ *   or reused - added immediately to the iwl->rxq->rx_free list.
+ * + When the page is stolen - the driver updates the matching queue's used
+ *   count, detaches the RBD and transfers it to the queue used list.
+ *   When there are two used RBDs - they are transferred to the allocator empty
+ *   list. Work is then scheduled for the allocator to start allocating
+ *   eight buffers.
+ *   When there are another 6 used RBDs - they are transferred to the allocator
+ *   empty list and the driver tries to claim the pre-allocated buffers and
+ *   add them to iwl->rxq->rx_free. If it fails - it continues to claim them
+ *   until ready.
+ *   When there are 8+ buffers in the free list - either from allocation or from
+ *   8 reused unstolen pages - restock is called to update the FW and indexes.
+ * + In order to make sure the allocator always has RBDs to use for allocation
+ *   the allocator has initial pool in the size of num_queues*(8-2) - the
+ *   maximum missing RBDs per allocation request (request posted with 2
+ *    empty RBDs, there is no guarantee when the other 6 RBDs are supplied).
+ *   The queues supplies the recycle of the rest of the RBDs.
  * + A received packet is processed and handed to the kernel network stack,
  *   detached from the iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at irq thread time from the
- *   rx_free list. If there are no allocated buffers in iwl->rxq->rx_free,
+ * + If there are no allocated buffers in iwl->rxq->rx_free,
  *   the READ INDEX is not incremented and iwl->status(RX_STALLED) is set.
  *   If there were enough free buffers and RX_STALLED is set it is cleared.
  *
  *
  * iwl_rxq_alloc()            Allocates rx_free
  * iwl_pcie_rx_replenish()    Replenishes rx_free list from rx_used, and calls
- *                            iwl_pcie_rxq_restock
+ *                            iwl_pcie_rxq_restock.
+ *                            Used only during initialization.
  * iwl_pcie_rxq_restock()     Moves available buffers from rx_free into Rx
  *                            queue, updates firmware pointers, and updates
- *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl_pcie_rx_replenish
+ *                            the WRITE index.
+ * iwl_pcie_rx_allocator()     Background work for allocating pages.
  *
  * -- enable interrupts --
  * ISR - iwl_rx()             Detach iwl_rx_mem_buffers from pool up to the
  *                            READ INDEX, detaching the SKB from the pool.
  *                            Moves the packet buffer from queue to rx_used.
+ *                            Posts and claims requests to the allocator.
  *                            Calls iwl_pcie_rxq_restock to refill any empty
  *                            slots.
+ *
+ * RBD life-cycle:
+ *
+ * Init:
+ * rxq.pool -> rxq.rx_used -> rxq.rx_free -> rxq.queue
+ *
+ * Regular Receive interrupt:
+ * Page Stolen:
+ * rxq.queue -> rxq.rx_used -> allocator.rbd_empty ->
+ * allocator.rbd_allocated -> rxq.rx_free -> rxq.queue
+ * Page not Stolen:
+ * rxq.queue -> rxq.rx_free -> rxq.queue
  * ...
  *
  */
@@ -240,10 +267,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
                rxq->free_count--;
        }
        spin_unlock(&rxq->lock);
-       /* If the pre-allocated buffer pool is dropping low, schedule to
-        * refill it */
-       if (rxq->free_count <= RX_LOW_WATERMARK)
-               schedule_work(&trans_pcie->rx_replenish);
 
        /* If we've added more space for the firmware to place data, tell it.
         * Increment device's write pointer in multiples of 8. */
@@ -254,6 +277,44 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
        }
 }
 
+/*
+ * iwl_pcie_rx_alloc_page - allocates and returns a page.
+ *
+ */
+static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rxq *rxq = &trans_pcie->rxq;
+       struct page *page;
+       gfp_t gfp_mask = GFP_KERNEL;
+
+       if (rxq->free_count > RX_LOW_WATERMARK)
+               gfp_mask |= __GFP_NOWARN;
+
+       if (trans_pcie->rx_page_order > 0)
+               gfp_mask |= __GFP_COMP;
+
+       /* Alloc a new receive buffer */
+       page = alloc_pages(gfp_mask, trans_pcie->rx_page_order);
+       if (!page) {
+               if (net_ratelimit())
+                       IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n",
+                                      trans_pcie->rx_page_order);
+               /* Issue an error if the hardware has consumed more than half
+                * of its free buffer list and we don't have enough
+                * pre-allocated buffers.
+`               */
+               if (rxq->free_count <= RX_LOW_WATERMARK &&
+                   iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) &&
+                   net_ratelimit())
+                       IWL_CRIT(trans,
+                                "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n",
+                                rxq->free_count);
+               return NULL;
+       }
+       return page;
+}
+
 /*
  * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD
  *
@@ -263,13 +324,12 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
  * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly
  * allocated buffers.
  */
-static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
+static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
        struct iwl_rx_mem_buffer *rxb;
        struct page *page;
-       gfp_t gfp_mask = priority;
 
        while (1) {
                spin_lock(&rxq->lock);
@@ -279,32 +339,10 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
                }
                spin_unlock(&rxq->lock);
 
-               if (rxq->free_count > RX_LOW_WATERMARK)
-                       gfp_mask |= __GFP_NOWARN;
-
-               if (trans_pcie->rx_page_order > 0)
-                       gfp_mask |= __GFP_COMP;
-
                /* Alloc a new receive buffer */
-               page = alloc_pages(gfp_mask, trans_pcie->rx_page_order);
-               if (!page) {
-                       if (net_ratelimit())
-                               IWL_DEBUG_INFO(trans, "alloc_pages failed, "
-                                          "order: %d\n",
-                                          trans_pcie->rx_page_order);
-
-                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-                           net_ratelimit())
-                               IWL_CRIT(trans, "Failed to alloc_pages with %s."
-                                        "Only %u free buffers remaining.\n",
-                                        priority == GFP_ATOMIC ?
-                                        "GFP_ATOMIC" : "GFP_KERNEL",
-                                        rxq->free_count);
-                       /* We don't reschedule replenish work here -- we will
-                        * call the restock method and if it still needs
-                        * more buffers it will schedule replenish */
+               page = iwl_pcie_rx_alloc_page(trans);
+               if (!page)
                        return;
-               }
 
                spin_lock(&rxq->lock);
 
@@ -355,7 +393,7 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
 
        lockdep_assert_held(&rxq->lock);
 
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+       for (i = 0; i < RX_QUEUE_SIZE; i++) {
                if (!rxq->pool[i].page)
                        continue;
                dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
@@ -372,32 +410,144 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
  * When moving to rx_free an page is allocated for the slot.
  *
  * Also restock the Rx queue via iwl_pcie_rxq_restock.
- * This is called as a scheduled work item (except for during initialization)
+ * This is called only during initialization
  */
-static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp)
+static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
 {
-       iwl_pcie_rxq_alloc_rbs(trans, gfp);
+       iwl_pcie_rxq_alloc_rbs(trans);
 
        iwl_pcie_rxq_restock(trans);
 }
 
-static void iwl_pcie_rx_replenish_work(struct work_struct *data)
+/*
+ * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues
+ *
+ * Allocates for each received request 8 pages
+ * Called as a scheduled work item.
+ */
+static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
+
+       while (atomic_read(&rba->req_pending)) {
+               int i;
+               struct list_head local_empty;
+               struct list_head local_allocated;
+
+               INIT_LIST_HEAD(&local_allocated);
+               spin_lock(&rba->lock);
+               /* swap out the entire rba->rbd_empty to a local list */
+               list_replace_init(&rba->rbd_empty, &local_empty);
+               spin_unlock(&rba->lock);
+
+               for (i = 0; i < RX_CLAIM_REQ_ALLOC;) {
+                       struct iwl_rx_mem_buffer *rxb;
+                       struct page *page;
+
+                       /* List should never be empty - each reused RBD is
+                        * returned to the list, and initial pool covers any
+                        * possible gap between the time the page is allocated
+                        * to the time the RBD is added.
+                        */
+                       BUG_ON(list_empty(&local_empty));
+                       /* Get the first rxb from the rbd list */
+                       rxb = list_first_entry(&local_empty,
+                                              struct iwl_rx_mem_buffer, list);
+                       BUG_ON(rxb->page);
+
+                       /* Alloc a new receive buffer */
+                       page = iwl_pcie_rx_alloc_page(trans);
+                       if (!page)
+                               continue;
+                       rxb->page = page;
+
+                       /* Get physical address of the RB */
+                       rxb->page_dma = dma_map_page(trans->dev, page, 0,
+                                       PAGE_SIZE << trans_pcie->rx_page_order,
+                                       DMA_FROM_DEVICE);
+                       if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                               rxb->page = NULL;
+                               __free_pages(page, trans_pcie->rx_page_order);
+                               continue;
+                       }
+                       /* dma address must be no more than 36 bits */
+                       BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+                       /* and also 256 byte aligned! */
+                       BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+                       /* move the allocated entry to the out list */
+                       list_move(&rxb->list, &local_allocated);
+                       i++;
+               }
+
+               spin_lock(&rba->lock);
+               /* add the allocated rbds to the allocator allocated list */
+               list_splice_tail(&local_allocated, &rba->rbd_allocated);
+               /* add the unused rbds back to the allocator empty list */
+               list_splice_tail(&local_empty, &rba->rbd_empty);
+               spin_unlock(&rba->lock);
+
+               atomic_dec(&rba->req_pending);
+               atomic_inc(&rba->req_ready);
+       }
+}
+
+/*
+ * iwl_pcie_rx_allocator_get - Returns the pre-allocated pages
+.*
+.* Called by queue when the queue posted allocation request and
+ * has freed 8 RBDs in order to restock itself.
+ */
+static int iwl_pcie_rx_allocator_get(struct iwl_trans *trans,
+                                    struct iwl_rx_mem_buffer
+                                    *out[RX_CLAIM_REQ_ALLOC])
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
+       int i;
+
+       if (atomic_dec_return(&rba->req_ready) < 0) {
+               atomic_inc(&rba->req_ready);
+               IWL_DEBUG_RX(trans,
+                            "Allocation request not ready, pending requests = %d\n",
+                            atomic_read(&rba->req_pending));
+               return -ENOMEM;
+       }
+
+       spin_lock(&rba->lock);
+       for (i = 0; i < RX_CLAIM_REQ_ALLOC; i++) {
+               /* Get next free Rx buffer, remove it from free list */
+               out[i] = list_first_entry(&rba->rbd_allocated,
+                              struct iwl_rx_mem_buffer, list);
+               list_del(&out[i]->list);
+       }
+       spin_unlock(&rba->lock);
+
+       return 0;
+}
+
+static void iwl_pcie_rx_allocator_work(struct work_struct *data)
 {
+       struct iwl_rb_allocator *rba_p =
+               container_of(data, struct iwl_rb_allocator, rx_alloc);
        struct iwl_trans_pcie *trans_pcie =
-           container_of(data, struct iwl_trans_pcie, rx_replenish);
+               container_of(rba_p, struct iwl_trans_pcie, rba);
 
-       iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL);
+       iwl_pcie_rx_allocator(trans_pcie->trans);
 }
 
 static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
        struct device *dev = trans->dev;
 
        memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
 
        spin_lock_init(&rxq->lock);
+       spin_lock_init(&rba->lock);
 
        if (WARN_ON(rxq->bd || rxq->rb_stts))
                return -EINVAL;
@@ -487,15 +637,49 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
        INIT_LIST_HEAD(&rxq->rx_free);
        INIT_LIST_HEAD(&rxq->rx_used);
        rxq->free_count = 0;
+       rxq->used_count = 0;
 
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+       for (i = 0; i < RX_QUEUE_SIZE; i++)
                list_add(&rxq->pool[i].list, &rxq->rx_used);
 }
 
+static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba)
+{
+       int i;
+
+       lockdep_assert_held(&rba->lock);
+
+       INIT_LIST_HEAD(&rba->rbd_allocated);
+       INIT_LIST_HEAD(&rba->rbd_empty);
+
+       for (i = 0; i < RX_POOL_SIZE; i++)
+               list_add(&rba->pool[i].list, &rba->rbd_empty);
+}
+
+static void iwl_pcie_rx_free_rba(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
+       int i;
+
+       lockdep_assert_held(&rba->lock);
+
+       for (i = 0; i < RX_POOL_SIZE; i++) {
+               if (!rba->pool[i].page)
+                       continue;
+               dma_unmap_page(trans->dev, rba->pool[i].page_dma,
+                              PAGE_SIZE << trans_pcie->rx_page_order,
+                              DMA_FROM_DEVICE);
+               __free_pages(rba->pool[i].page, trans_pcie->rx_page_order);
+               rba->pool[i].page = NULL;
+       }
+}
+
 int iwl_pcie_rx_init(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
        int i, err;
 
        if (!rxq->bd) {
@@ -503,11 +687,21 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
                if (err)
                        return err;
        }
+       if (!rba->alloc_wq)
+               rba->alloc_wq = alloc_workqueue("rb_allocator",
+                                               WQ_HIGHPRI | WQ_UNBOUND, 1);
+       INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work);
+
+       spin_lock(&rba->lock);
+       atomic_set(&rba->req_pending, 0);
+       atomic_set(&rba->req_ready, 0);
+       /* free all first - we might be reconfigured for a different size */
+       iwl_pcie_rx_free_rba(trans);
+       iwl_pcie_rx_init_rba(rba);
+       spin_unlock(&rba->lock);
 
        spin_lock(&rxq->lock);
 
-       INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work);
-
        /* free all first - we might be reconfigured for a different size */
        iwl_pcie_rxq_free_rbs(trans);
        iwl_pcie_rx_init_rxb_lists(rxq);
@@ -522,7 +716,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
        memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
        spin_unlock(&rxq->lock);
 
-       iwl_pcie_rx_replenish(trans, GFP_KERNEL);
+       iwl_pcie_rx_replenish(trans);
 
        iwl_pcie_rx_hw_init(trans, rxq);
 
@@ -537,6 +731,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
 
        /*if rxq->bd is NULL, it means that nothing has been allocated,
         * exit now */
@@ -545,7 +740,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
                return;
        }
 
-       cancel_work_sync(&trans_pcie->rx_replenish);
+       cancel_work_sync(&rba->rx_alloc);
+       if (rba->alloc_wq) {
+               destroy_workqueue(rba->alloc_wq);
+               rba->alloc_wq = NULL;
+       }
+
+       spin_lock(&rba->lock);
+       iwl_pcie_rx_free_rba(trans);
+       spin_unlock(&rba->lock);
 
        spin_lock(&rxq->lock);
        iwl_pcie_rxq_free_rbs(trans);
@@ -566,6 +769,43 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
        rxq->rb_stts = NULL;
 }
 
+/*
+ * iwl_pcie_rx_reuse_rbd - Recycle used RBDs
+ *
+ * Called when a RBD can be reused. The RBD is transferred to the allocator.
+ * When there are 2 empty RBDs - a request for allocation is posted
+ */
+static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans,
+                                 struct iwl_rx_mem_buffer *rxb,
+                                 struct iwl_rxq *rxq)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rb_allocator *rba = &trans_pcie->rba;
+
+       /* Count the used RBDs */
+       rxq->used_count++;
+
+       /* Move the RBD to the used list, will be moved to allocator in batches
+        * before claiming or posting a request*/
+       list_add_tail(&rxb->list, &rxq->rx_used);
+
+       /* If we have RX_POST_REQ_ALLOC new released rx buffers -
+        * issue a request for allocator. Modulo RX_CLAIM_REQ_ALLOC is
+        * used for the case we failed to claim RX_CLAIM_REQ_ALLOC,
+        * after but we still need to post another request.
+        */
+       if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) {
+               /* Move the 2 RBDs to the allocator ownership.
+                Allocator has another 6 from pool for the request completion*/
+               spin_lock(&rba->lock);
+               list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
+               spin_unlock(&rba->lock);
+
+               atomic_inc(&rba->req_pending);
+               queue_work(rba->alloc_wq, &rba->rx_alloc);
+       }
+}
+
 static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                                struct iwl_rx_mem_buffer *rxb)
 {
@@ -688,13 +928,13 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                         */
                        __free_pages(rxb->page, trans_pcie->rx_page_order);
                        rxb->page = NULL;
-                       list_add_tail(&rxb->list, &rxq->rx_used);
+                       iwl_pcie_rx_reuse_rbd(trans, rxb, rxq);
                } else {
                        list_add_tail(&rxb->list, &rxq->rx_free);
                        rxq->free_count++;
                }
        } else
-               list_add_tail(&rxb->list, &rxq->rx_used);
+               iwl_pcie_rx_reuse_rbd(trans, rxb, rxq);
 }
 
 /*
@@ -704,10 +944,7 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_rxq *rxq = &trans_pcie->rxq;
-       u32 r, i;
-       u8 fill_rx = 0;
-       u32 count = 8;
-       int total_empty;
+       u32 r, i, j;
 
 restart:
        spin_lock(&rxq->lock);
@@ -720,14 +957,6 @@ restart:
        if (i == r)
                IWL_DEBUG_RX(trans, "HW = SW = %d\n", r);
 
-       /* calculate total frames need to be restock after handling RX */
-       total_empty = r - rxq->write_actual;
-       if (total_empty < 0)
-               total_empty += RX_QUEUE_SIZE;
-
-       if (total_empty > (RX_QUEUE_SIZE / 2))
-               fill_rx = 1;
-
        while (i != r) {
                struct iwl_rx_mem_buffer *rxb;
 
@@ -739,29 +968,48 @@ restart:
                iwl_pcie_rx_handle_rb(trans, rxb);
 
                i = (i + 1) & RX_QUEUE_MASK;
-               /* If there are a lot of unused frames,
-                * restock the Rx queue so ucode wont assert. */
-               if (fill_rx) {
-                       count++;
-                       if (count >= 8) {
-                               rxq->read = i;
-                               spin_unlock(&rxq->lock);
-                               iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
-                               count = 0;
-                               goto restart;
+
+               /* If we have RX_CLAIM_REQ_ALLOC released rx buffers -
+                * try to claim the pre-allocated buffers from the allocator */
+               if (rxq->used_count >= RX_CLAIM_REQ_ALLOC) {
+                       struct iwl_rb_allocator *rba = &trans_pcie->rba;
+                       struct iwl_rx_mem_buffer *out[RX_CLAIM_REQ_ALLOC];
+
+                       /* Add the remaining 6 empty RBDs for allocator use */
+                       spin_lock(&rba->lock);
+                       list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
+                       spin_unlock(&rba->lock);
+
+                       /* If not ready - continue, will try to reclaim later.
+                       * No need to reschedule work - allocator exits only on
+                       * success */
+                       if (!iwl_pcie_rx_allocator_get(trans, out)) {
+                               /* If success - then RX_CLAIM_REQ_ALLOC
+                                * buffers were retrieved and should be added
+                                * to free list */
+                               rxq->used_count -= RX_CLAIM_REQ_ALLOC;
+                               for (j = 0; j < RX_CLAIM_REQ_ALLOC; j++) {
+                                       list_add_tail(&out[j]->list,
+                                                     &rxq->rx_free);
+                                       rxq->free_count++;
+                               }
                        }
                }
+               /* handle restock for two cases:
+               * - we just pulled buffers from the allocator
+               * - we have 8+ unstolen pages accumulated */
+               if (rxq->free_count >=  RX_CLAIM_REQ_ALLOC) {
+                       rxq->read = i;
+                       spin_unlock(&rxq->lock);
+                       iwl_pcie_rxq_restock(trans);
+                       goto restart;
+               }
        }
 
        /* Backtrack one entry */
        rxq->read = i;
        spin_unlock(&rxq->lock);
 
-       if (fill_rx)
-               iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
-       else
-               iwl_pcie_rxq_restock(trans);
-
        if (trans_pcie->napi.poll)
                napi_gro_flush(&trans_pcie->napi, false);
 }
@@ -775,6 +1023,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 
        /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
        if (trans->cfg->internal_wimax_coex &&
+           !trans->cfg->apmg_not_supported &&
            (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
                             APMS_CLK_VAL_MRB_FUNC_MODE) ||
             (iwl_read_prph(trans, APMG_PS_CTRL_REG) &
index 7f4914f0af0efd10a11378c4097444e205969959..43ae658af6ec56506f9f0e8ed00022b890c3b9fb 100644 (file)
@@ -182,6 +182,9 @@ static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val)
 
 static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
 {
+       if (!trans->cfg->apmg_not_supported)
+               return;
+
        if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
                iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG,
                                       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
@@ -315,7 +318,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
         * bits do not disable clocks.  This preserves any hardware
         * bits already set by default in "CLK_CTRL_REG" after reset.
         */
-       if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+       if (!trans->cfg->apmg_not_supported) {
                iwl_write_prph(trans, APMG_CLK_EN_REG,
                               APMG_CLK_VAL_DMA_CLK_RQT);
                udelay(20);
@@ -515,8 +518,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
 
        spin_unlock(&trans_pcie->irq_lock);
 
-       if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
-               iwl_pcie_set_pwr(trans, false);
+       iwl_pcie_set_pwr(trans, false);
 
        iwl_op_mode_nic_config(trans->op_mode);
 
@@ -973,12 +975,8 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
                return ret;
 
        /* load to FW the binary sections of CPU2 */
-       ret = iwl_pcie_load_cpu_sections_8000(trans, image, 2,
-                                             &first_ucode_section);
-       if (ret)
-               return ret;
-
-       return 0;
+       return iwl_pcie_load_cpu_sections_8000(trans, image, 2,
+                                              &first_ucode_section);
 }
 
 static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
@@ -1067,7 +1065,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
                iwl_pcie_rx_stop(trans);
 
                /* Power-down device's busmaster DMA clocks */
-               if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+               if (!trans->cfg->apmg_not_supported) {
                        iwl_write_prph(trans, APMG_CLK_DIS_REG,
                                       APMG_CLK_VAL_DMA_CLK_RQT);
                        udelay(5);
@@ -1364,14 +1362,13 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
        iounmap(trans_pcie->hw_base);
        pci_release_regions(trans_pcie->pci_dev);
        pci_disable_device(trans_pcie->pci_dev);
-       kmem_cache_destroy(trans->dev_cmd_pool);
 
        if (trans_pcie->napi.poll)
                netif_napi_del(&trans_pcie->napi);
 
        iwl_pcie_free_fw_monitor(trans);
 
-       kfree(trans);
+       iwl_trans_free(trans);
 }
 
 static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state)
@@ -2464,18 +2461,13 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        u16 pci_cmd;
        int err;
 
-       trans = kzalloc(sizeof(struct iwl_trans) +
-                       sizeof(struct iwl_trans_pcie), GFP_KERNEL);
-       if (!trans) {
-               err = -ENOMEM;
-               goto out;
-       }
+       trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
+                               &pdev->dev, cfg, &trans_ops_pcie, 0);
+       if (!trans)
+               return ERR_PTR(-ENOMEM);
 
        trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       trans->ops = &trans_ops_pcie;
-       trans->cfg = cfg;
-       trans_lockdep_init(trans);
        trans_pcie->trans = trans;
        spin_lock_init(&trans_pcie->irq_lock);
        spin_lock_init(&trans_pcie->reg_lock);
@@ -2599,25 +2591,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        /* Initialize the wait queue for commands */
        init_waitqueue_head(&trans_pcie->wait_command_queue);
 
-       snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
-                "iwl_cmd_pool:%s", dev_name(trans->dev));
-
-       trans->dev_cmd_headroom = 0;
-       trans->dev_cmd_pool =
-               kmem_cache_create(trans->dev_cmd_pool_name,
-                                 sizeof(struct iwl_device_cmd)
-                                 + trans->dev_cmd_headroom,
-                                 sizeof(void *),
-                                 SLAB_HWCACHE_ALIGN,
-                                 NULL);
-
-       if (!trans->dev_cmd_pool) {
-               err = -ENOMEM;
-               goto out_pci_disable_msi;
-       }
-
        if (iwl_pcie_alloc_ict(trans))
-               goto out_free_cmd_pool;
+               goto out_pci_disable_msi;
 
        err = request_threaded_irq(pdev->irq, iwl_pcie_isr,
                                   iwl_pcie_irq_handler,
@@ -2634,8 +2609,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
 out_free_ict:
        iwl_pcie_free_ict(trans);
-out_free_cmd_pool:
-       kmem_cache_destroy(trans->dev_cmd_pool);
 out_pci_disable_msi:
        pci_disable_msi(pdev);
 out_pci_release_regions:
@@ -2643,7 +2616,6 @@ out_pci_release_regions:
 out_pci_disable_device:
        pci_disable_device(pdev);
 out_no_pci:
-       kfree(trans);
-out:
+       iwl_trans_free(trans);
        return ERR_PTR(err);
 }
index 5ef8044c2ea3ed7317870902168c71be936cd8df..2b86c2135de36f627b397add88628bc47aa37271 100644 (file)
@@ -1049,8 +1049,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
            !trans_pcie->cmd_hold_nic_awake) {
                __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
                                         CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-               if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-                       udelay(2);
 
                ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
                                   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
diff --git a/drivers/net/wireless/mediatek/Kconfig b/drivers/net/wireless/mediatek/Kconfig
new file mode 100644 (file)
index 0000000..cba300c
--- /dev/null
@@ -0,0 +1,10 @@
+menuconfig WL_MEDIATEK
+       bool "Mediatek Wireless LAN support"
+       ---help---
+         Enable community drivers for MediaTek WiFi devices.
+         Those drivers make use of the Linux mac80211 stack.
+
+
+if WL_MEDIATEK
+source "drivers/net/wireless/mediatek/mt7601u/Kconfig"
+endif # WL_MEDIATEK
diff --git a/drivers/net/wireless/mediatek/Makefile b/drivers/net/wireless/mediatek/Makefile
new file mode 100644 (file)
index 0000000..9d5f182
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_MT7601U)  += mt7601u/
diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig
new file mode 100644 (file)
index 0000000..f46bed9
--- /dev/null
@@ -0,0 +1,6 @@
+config MT7601U
+       tristate "MediaTek MT7601U (USB) support"
+       depends on MAC80211
+       depends on USB
+       ---help---
+         This adds support for MT7601U-based wireless USB dongles.
diff --git a/drivers/net/wireless/mediatek/mt7601u/Makefile b/drivers/net/wireless/mediatek/mt7601u/Makefile
new file mode 100644 (file)
index 0000000..ea9ed8a
--- /dev/null
@@ -0,0 +1,9 @@
+ccflags-y += -D__CHECK_ENDIAN__
+
+obj-$(CONFIG_MT7601U)  += mt7601u.o
+
+mt7601u-objs   = \
+       usb.o init.o main.o mcu.o trace.o dma.o core.o eeprom.o phy.o \
+       mac.o util.o debugfs.o tx.o
+
+CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/mediatek/mt7601u/core.c b/drivers/net/wireless/mediatek/mt7601u/core.c
new file mode 100644 (file)
index 0000000..0aabd79
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+
+int mt7601u_wait_asic_ready(struct mt7601u_dev *dev)
+{
+       int i = 100;
+       u32 val;
+
+       do {
+               if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+                       return -EIO;
+
+               val = mt7601u_rr(dev, MT_MAC_CSR0);
+               if (val && ~val)
+                       return 0;
+
+               udelay(10);
+       } while (i--);
+
+       return -EIO;
+}
+
+bool mt76_poll(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
+              int timeout)
+{
+       u32 cur;
+
+       timeout /= 10;
+       do {
+               if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+                       return false;
+
+               cur = mt7601u_rr(dev, offset) & mask;
+               if (cur == val)
+                       return true;
+
+               udelay(10);
+       } while (timeout-- > 0);
+
+       dev_err(dev->dev, "Error: Time out with reg %08x\n", offset);
+
+       return false;
+}
+
+bool mt76_poll_msec(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
+                   int timeout)
+{
+       u32 cur;
+
+       timeout /= 10;
+       do {
+               if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+                       return false;
+
+               cur = mt7601u_rr(dev, offset) & mask;
+               if (cur == val)
+                       return true;
+
+               msleep(10);
+       } while (timeout-- > 0);
+
+       dev_err(dev->dev, "Error: Time out with reg %08x\n", offset);
+
+       return false;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
new file mode 100644 (file)
index 0000000..fc00847
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include <linux/debugfs.h>
+
+#include "mt7601u.h"
+#include "eeprom.h"
+
+static int
+mt76_reg_set(void *data, u64 val)
+{
+       struct mt7601u_dev *dev = data;
+
+       mt76_wr(dev, dev->debugfs_reg, val);
+       return 0;
+}
+
+static int
+mt76_reg_get(void *data, u64 *val)
+{
+       struct mt7601u_dev *dev = data;
+
+       *val = mt76_rr(dev, dev->debugfs_reg);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
+
+static int
+mt7601u_ampdu_stat_read(struct seq_file *file, void *data)
+{
+       struct mt7601u_dev *dev = file->private;
+       int i, j;
+
+#define stat_printf(grp, off, name)                                    \
+       seq_printf(file, #name ":\t%llu\n", dev->stats.grp[off])
+
+       stat_printf(rx_stat, 0, rx_crc_err);
+       stat_printf(rx_stat, 1, rx_phy_err);
+       stat_printf(rx_stat, 2, rx_false_cca);
+       stat_printf(rx_stat, 3, rx_plcp_err);
+       stat_printf(rx_stat, 4, rx_fifo_overflow);
+       stat_printf(rx_stat, 5, rx_duplicate);
+
+       stat_printf(tx_stat, 0, tx_fail_cnt);
+       stat_printf(tx_stat, 1, tx_bcn_cnt);
+       stat_printf(tx_stat, 2, tx_success);
+       stat_printf(tx_stat, 3, tx_retransmit);
+       stat_printf(tx_stat, 4, tx_zero_len);
+       stat_printf(tx_stat, 5, tx_underflow);
+
+       stat_printf(aggr_stat, 0, non_aggr_tx);
+       stat_printf(aggr_stat, 1, aggr_tx);
+
+       stat_printf(zero_len_del, 0, tx_zero_len_del);
+       stat_printf(zero_len_del, 1, rx_zero_len_del);
+#undef stat_printf
+
+       seq_puts(file, "Aggregations stats:\n");
+       for (i = 0; i < 4; i++) {
+               for (j = 0; j < 8; j++)
+                       seq_printf(file, "%08llx ",
+                                  dev->stats.aggr_n[i * 8 + j]);
+               seq_putc(file, '\n');
+       }
+
+       seq_printf(file, "recent average AMPDU len: %d\n",
+                  atomic_read(&dev->avg_ampdu_len));
+
+       return 0;
+}
+
+static int
+mt7601u_ampdu_stat_open(struct inode *inode, struct file *f)
+{
+       return single_open(f, mt7601u_ampdu_stat_read, inode->i_private);
+}
+
+static const struct file_operations fops_ampdu_stat = {
+       .open = mt7601u_ampdu_stat_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int
+mt7601u_eeprom_param_read(struct seq_file *file, void *data)
+{
+       struct mt7601u_dev *dev = file->private;
+       struct mt7601u_rate_power *rp = &dev->ee->power_rate_table;
+       struct tssi_data *td = &dev->ee->tssi_data;
+       int i;
+
+       seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off);
+       seq_printf(file, "RSSI offset: %hhx %hhx\n",
+                  dev->ee->rssi_offset[0], dev->ee->rssi_offset[1]);
+       seq_printf(file, "Reference temp: %hhx\n", dev->ee->ref_temp);
+       seq_printf(file, "LNA gain: %hhx\n", dev->ee->lna_gain);
+       seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start,
+                  dev->ee->reg.start + dev->ee->reg.num - 1);
+
+       seq_puts(file, "Per rate power:\n");
+       for (i = 0; i < 2; i++)
+               seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
+                          rp->cck[i].raw, rp->cck[i].bw20, rp->cck[i].bw40);
+       for (i = 0; i < 4; i++)
+               seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
+                          rp->ofdm[i].raw, rp->ofdm[i].bw20, rp->ofdm[i].bw40);
+       for (i = 0; i < 4; i++)
+               seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
+                          rp->ht[i].raw, rp->ht[i].bw20, rp->ht[i].bw40);
+
+       seq_puts(file, "Per channel power:\n");
+       for (i = 0; i < 7; i++)
+               seq_printf(file, "\t tx_power  ch%u:%02hhx ch%u:%02hhx\n",
+                          i * 2 + 1, dev->ee->chan_pwr[i * 2],
+                          i * 2 + 2, dev->ee->chan_pwr[i * 2 + 1]);
+
+       if (!dev->ee->tssi_enabled)
+               return 0;
+
+       seq_puts(file, "TSSI:\n");
+       seq_printf(file, "\t slope:%02hhx\n", td->slope);
+       seq_printf(file, "\t offset=%02hhx %02hhx %02hhx\n",
+                  td->offset[0], td->offset[1], td->offset[2]);
+       seq_printf(file, "\t delta_off:%08x\n", td->tx0_delta_offset);
+
+       return 0;
+}
+
+static int
+mt7601u_eeprom_param_open(struct inode *inode, struct file *f)
+{
+       return single_open(f, mt7601u_eeprom_param_read, inode->i_private);
+}
+
+static const struct file_operations fops_eeprom_param = {
+       .open = mt7601u_eeprom_param_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+void mt7601u_init_debugfs(struct mt7601u_dev *dev)
+{
+       struct dentry *dir;
+
+       dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
+       if (!dir)
+               return;
+
+       debugfs_create_u8("temperature", S_IRUSR, dir, &dev->raw_temp);
+       debugfs_create_u32("temp_mode", S_IRUSR, dir, &dev->temp_mode);
+
+       debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
+       debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
+                           &fops_regval);
+       debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
+       debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
+                           &fops_eeprom_param);
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
new file mode 100644 (file)
index 0000000..9c9e128
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "dma.h"
+#include "usb.h"
+#include "trace.h"
+
+static int mt7601u_submit_rx_buf(struct mt7601u_dev *dev,
+                                struct mt7601u_dma_buf_rx *e, gfp_t gfp);
+
+static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
+{
+       const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data;
+       unsigned int hdrlen;
+
+       if (unlikely(len < 10))
+               return 0;
+       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+       if (unlikely(hdrlen > len))
+               return 0;
+       return hdrlen;
+}
+
+static struct sk_buff *
+mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
+                       u8 *data, u32 seg_len)
+{
+       struct sk_buff *skb;
+       u32 true_len;
+
+       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD))
+               seg_len -= 2;
+
+       skb = alloc_skb(seg_len, GFP_ATOMIC);
+       if (!skb)
+               return NULL;
+
+       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
+               int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
+
+               memcpy(skb_put(skb, hdr_len), data, hdr_len);
+               data += hdr_len + 2;
+               seg_len -= hdr_len;
+       }
+
+       memcpy(skb_put(skb, seg_len), data, seg_len);
+
+       true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi);
+       skb_trim(skb, true_len);
+
+       return skb;
+}
+
+static struct sk_buff *
+mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
+                             struct mt7601u_rxwi *rxwi, void *data,
+                             u32 seg_len, u32 truesize, struct page *p)
+{
+       unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
+       unsigned int true_len, copy, frag;
+       struct sk_buff *skb;
+
+       skb = alloc_skb(128, GFP_ATOMIC);
+       if (!skb)
+               return NULL;
+
+       true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
+
+       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
+               memcpy(skb_put(skb, hdr_len), data, hdr_len);
+               data += hdr_len + 2;
+               true_len -= hdr_len;
+               hdr_len = 0;
+       }
+
+       copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
+       frag = true_len - copy;
+
+       memcpy(skb_put(skb, copy), data, copy);
+       data += copy;
+
+       if (frag) {
+               skb_add_rx_frag(skb, 0, p, data - page_address(p),
+                               frag, truesize);
+               get_page(p);
+       }
+
+       return skb;
+}
+
+static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
+                                  u32 seg_len, struct page *p, bool paged)
+{
+       struct sk_buff *skb;
+       struct mt7601u_rxwi *rxwi;
+       u32 fce_info, truesize = seg_len;
+
+       /* DMA_INFO field at the beginning of the segment contains only some of
+        * the information, we need to read the FCE descriptor from the end.
+        */
+       fce_info = get_unaligned_le32(data + seg_len - MT_FCE_INFO_LEN);
+       seg_len -= MT_FCE_INFO_LEN;
+
+       data += MT_DMA_HDR_LEN;
+       seg_len -= MT_DMA_HDR_LEN;
+
+       rxwi = (struct mt7601u_rxwi *) data;
+       data += sizeof(struct mt7601u_rxwi);
+       seg_len -= sizeof(struct mt7601u_rxwi);
+
+       if (unlikely(rxwi->zero[0] || rxwi->zero[1] || rxwi->zero[2]))
+               dev_err_once(dev->dev, "Error: RXWI zero fields are set\n");
+       if (unlikely(MT76_GET(MT_RXD_INFO_TYPE, fce_info)))
+               dev_err_once(dev->dev, "Error: RX path seen a non-pkt urb\n");
+
+       trace_mt_rx(dev, rxwi, fce_info);
+
+       if (paged)
+               skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len,
+                                                   truesize, p);
+       else
+               skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len);
+       if (!skb)
+               return;
+
+       ieee80211_rx_ni(dev->hw, skb);
+}
+
+static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)
+{
+       u32 min_seg_len = MT_DMA_HDR_LEN + MT_RX_INFO_LEN +
+               sizeof(struct mt7601u_rxwi) + MT_FCE_INFO_LEN;
+       u16 dma_len = get_unaligned_le16(data);
+
+       if (data_len < min_seg_len ||
+           WARN_ON(!dma_len) ||
+           WARN_ON(dma_len + MT_DMA_HDRS > data_len) ||
+           WARN_ON(dma_len & 0x3))
+               return 0;
+
+       return MT_DMA_HDRS + dma_len;
+}
+
+static void
+mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
+{
+       u32 seg_len, data_len = e->urb->actual_length;
+       u8 *data = page_address(e->p);
+       struct page *new_p = NULL;
+       bool paged = true;
+       int cnt = 0;
+
+       if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state))
+               return;
+
+       /* Copy if there is very little data in the buffer. */
+       if (data_len < 512) {
+               paged = false;
+       } else {
+               new_p = dev_alloc_pages(MT_RX_ORDER);
+               if (!new_p)
+                       paged = false;
+       }
+
+       while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) {
+               mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged);
+
+               data_len -= seg_len;
+               data += seg_len;
+               cnt++;
+       }
+
+       if (cnt > 1)
+               trace_mt_rx_dma_aggr(dev, cnt, paged);
+
+       if (paged) {
+               /* we have one extra ref from the allocator */
+               __free_pages(e->p, MT_RX_ORDER);
+
+               e->p = new_p;
+       }
+}
+
+static struct mt7601u_dma_buf_rx *
+mt7601u_rx_get_pending_entry(struct mt7601u_dev *dev)
+{
+       struct mt7601u_rx_queue *q = &dev->rx_q;
+       struct mt7601u_dma_buf_rx *buf = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->rx_lock, flags);
+
+       if (!q->pending)
+               goto out;
+
+       buf = &q->e[q->start];
+       q->pending--;
+       q->start = (q->start + 1) % q->entries;
+out:
+       spin_unlock_irqrestore(&dev->rx_lock, flags);
+
+       return buf;
+}
+
+static void mt7601u_complete_rx(struct urb *urb)
+{
+       struct mt7601u_dev *dev = urb->context;
+       struct mt7601u_rx_queue *q = &dev->rx_q;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->rx_lock, flags);
+
+       if (mt7601u_urb_has_error(urb))
+               dev_err(dev->dev, "Error: RX urb failed:%d\n", urb->status);
+       if (WARN_ONCE(q->e[q->end].urb != urb, "RX urb mismatch"))
+               goto out;
+
+       q->end = (q->end + 1) % q->entries;
+       q->pending++;
+       tasklet_schedule(&dev->rx_tasklet);
+out:
+       spin_unlock_irqrestore(&dev->rx_lock, flags);
+}
+
+static void mt7601u_rx_tasklet(unsigned long data)
+{
+       struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
+       struct mt7601u_dma_buf_rx *e;
+
+       while ((e = mt7601u_rx_get_pending_entry(dev))) {
+               if (e->urb->status)
+                       continue;
+
+               mt7601u_rx_process_entry(dev, e);
+               mt7601u_submit_rx_buf(dev, e, GFP_ATOMIC);
+       }
+}
+
+static void mt7601u_complete_tx(struct urb *urb)
+{
+       struct mt7601u_tx_queue *q = urb->context;
+       struct mt7601u_dev *dev = q->dev;
+       struct sk_buff *skb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->tx_lock, flags);
+
+       if (mt7601u_urb_has_error(urb))
+               dev_err(dev->dev, "Error: TX urb failed:%d\n", urb->status);
+       if (WARN_ONCE(q->e[q->start].urb != urb, "TX urb mismatch"))
+               goto out;
+
+       skb = q->e[q->start].skb;
+       trace_mt_tx_dma_done(dev, skb);
+
+       mt7601u_tx_status(dev, skb);
+
+       if (q->used == q->entries - q->entries / 8)
+               ieee80211_wake_queue(dev->hw, skb_get_queue_mapping(skb));
+
+       q->start = (q->start + 1) % q->entries;
+       q->used--;
+
+       if (urb->status)
+               goto out;
+
+       set_bit(MT7601U_STATE_MORE_STATS, &dev->state);
+       if (!test_and_set_bit(MT7601U_STATE_READING_STATS, &dev->state))
+               queue_delayed_work(dev->stat_wq, &dev->stat_work,
+                                  msecs_to_jiffies(10));
+out:
+       spin_unlock_irqrestore(&dev->tx_lock, flags);
+}
+
+static int mt7601u_dma_submit_tx(struct mt7601u_dev *dev,
+                                struct sk_buff *skb, u8 ep)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+       unsigned snd_pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep]);
+       struct mt7601u_dma_buf_tx *e;
+       struct mt7601u_tx_queue *q = &dev->tx_q[ep];
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&dev->tx_lock, flags);
+
+       if (WARN_ON(q->entries <= q->used)) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       e = &q->e[q->end];
+       e->skb = skb;
+       usb_fill_bulk_urb(e->urb, usb_dev, snd_pipe, skb->data, skb->len,
+                         mt7601u_complete_tx, q);
+       ret = usb_submit_urb(e->urb, GFP_ATOMIC);
+       if (ret) {
+               /* Special-handle ENODEV from TX urb submission because it will
+                * often be the first ENODEV we see after device is removed.
+                */
+               if (ret == -ENODEV)
+                       set_bit(MT7601U_STATE_REMOVED, &dev->state);
+               else
+                       dev_err(dev->dev, "Error: TX urb submit failed:%d\n",
+                               ret);
+               goto out;
+       }
+
+       q->end = (q->end + 1) % q->entries;
+       q->used++;
+
+       if (q->used >= q->entries)
+               ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb));
+out:
+       spin_unlock_irqrestore(&dev->tx_lock, flags);
+
+       return ret;
+}
+
+/* Map hardware Q to USB endpoint number */
+static u8 q2ep(u8 qid)
+{
+       /* TODO: take management packets to queue 5 */
+       return qid + 1;
+}
+
+/* Map USB endpoint number to Q id in the DMA engine */
+static enum mt76_qsel ep2dmaq(u8 ep)
+{
+       if (ep == 5)
+               return MT_QSEL_MGMT;
+       return MT_QSEL_EDCA;
+}
+
+int mt7601u_dma_enqueue_tx(struct mt7601u_dev *dev, struct sk_buff *skb,
+                          struct mt76_wcid *wcid, int hw_q)
+{
+       u8 ep = q2ep(hw_q);
+       u32 dma_flags;
+       int ret;
+
+       dma_flags = MT_TXD_PKT_INFO_80211;
+       if (wcid->hw_key_idx == 0xff)
+               dma_flags |= MT_TXD_PKT_INFO_WIV;
+
+       ret = mt7601u_dma_skb_wrap_pkt(skb, ep2dmaq(ep), dma_flags);
+       if (ret)
+               return ret;
+
+       ret = mt7601u_dma_submit_tx(dev, skb, ep);
+       if (ret) {
+               ieee80211_free_txskb(dev->hw, skb);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void mt7601u_kill_rx(struct mt7601u_dev *dev)
+{
+       int i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->rx_lock, flags);
+
+       for (i = 0; i < dev->rx_q.entries; i++) {
+               int next = dev->rx_q.end;
+
+               spin_unlock_irqrestore(&dev->rx_lock, flags);
+               usb_poison_urb(dev->rx_q.e[next].urb);
+               spin_lock_irqsave(&dev->rx_lock, flags);
+       }
+
+       spin_unlock_irqrestore(&dev->rx_lock, flags);
+}
+
+static int mt7601u_submit_rx_buf(struct mt7601u_dev *dev,
+                                struct mt7601u_dma_buf_rx *e, gfp_t gfp)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+       u8 *buf = page_address(e->p);
+       unsigned pipe;
+       int ret;
+
+       pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[MT_EP_IN_PKT_RX]);
+
+       usb_fill_bulk_urb(e->urb, usb_dev, pipe, buf, MT_RX_URB_SIZE,
+                         mt7601u_complete_rx, dev);
+
+       trace_mt_submit_urb(dev, e->urb);
+       ret = usb_submit_urb(e->urb, gfp);
+       if (ret)
+               dev_err(dev->dev, "Error: submit RX URB failed:%d\n", ret);
+
+       return ret;
+}
+
+static int mt7601u_submit_rx(struct mt7601u_dev *dev)
+{
+       int i, ret;
+
+       for (i = 0; i < dev->rx_q.entries; i++) {
+               ret = mt7601u_submit_rx_buf(dev, &dev->rx_q.e[i], GFP_KERNEL);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void mt7601u_free_rx(struct mt7601u_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < dev->rx_q.entries; i++) {
+               __free_pages(dev->rx_q.e[i].p, MT_RX_ORDER);
+               usb_free_urb(dev->rx_q.e[i].urb);
+       }
+}
+
+static int mt7601u_alloc_rx(struct mt7601u_dev *dev)
+{
+       int i;
+
+       memset(&dev->rx_q, 0, sizeof(dev->rx_q));
+       dev->rx_q.dev = dev;
+       dev->rx_q.entries = N_RX_ENTRIES;
+
+       for (i = 0; i < N_RX_ENTRIES; i++) {
+               dev->rx_q.e[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+               dev->rx_q.e[i].p = dev_alloc_pages(MT_RX_ORDER);
+
+               if (!dev->rx_q.e[i].urb || !dev->rx_q.e[i].p)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void mt7601u_free_tx_queue(struct mt7601u_tx_queue *q)
+{
+       int i;
+
+       WARN_ON(q->used);
+
+       for (i = 0; i < q->entries; i++)  {
+               usb_poison_urb(q->e[i].urb);
+               usb_free_urb(q->e[i].urb);
+       }
+}
+
+static void mt7601u_free_tx(struct mt7601u_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < __MT_EP_OUT_MAX; i++)
+               mt7601u_free_tx_queue(&dev->tx_q[i]);
+}
+
+static int mt7601u_alloc_tx_queue(struct mt7601u_dev *dev,
+                                 struct mt7601u_tx_queue *q)
+{
+       int i;
+
+       q->dev = dev;
+       q->entries = N_TX_ENTRIES;
+
+       for (i = 0; i < N_TX_ENTRIES; i++) {
+               q->e[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!q->e[i].urb)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int mt7601u_alloc_tx(struct mt7601u_dev *dev)
+{
+       int i;
+
+       dev->tx_q = devm_kcalloc(dev->dev, __MT_EP_OUT_MAX,
+                                sizeof(*dev->tx_q), GFP_KERNEL);
+
+       for (i = 0; i < __MT_EP_OUT_MAX; i++)
+               if (mt7601u_alloc_tx_queue(dev, &dev->tx_q[i]))
+                       return -ENOMEM;
+
+       return 0;
+}
+
+int mt7601u_dma_init(struct mt7601u_dev *dev)
+{
+       int ret = -ENOMEM;
+
+       tasklet_init(&dev->rx_tasklet, mt7601u_rx_tasklet, (unsigned long) dev);
+
+       ret = mt7601u_alloc_tx(dev);
+       if (ret)
+               goto err;
+       ret = mt7601u_alloc_rx(dev);
+       if (ret)
+               goto err;
+
+       ret = mt7601u_submit_rx(dev);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       mt7601u_dma_cleanup(dev);
+       return ret;
+}
+
+void mt7601u_dma_cleanup(struct mt7601u_dev *dev)
+{
+       mt7601u_kill_rx(dev);
+
+       tasklet_kill(&dev->rx_tasklet);
+
+       mt7601u_free_rx(dev);
+       mt7601u_free_tx(dev);
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.h b/drivers/net/wireless/mediatek/mt7601u/dma.h
new file mode 100644 (file)
index 0000000..978e8a9
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_DMA_H
+#define __MT7601U_DMA_H
+
+#include <asm/unaligned.h>
+#include <linux/skbuff.h>
+
+#include "util.h"
+
+#define MT_DMA_HDR_LEN                 4
+#define MT_RX_INFO_LEN                 4
+#define MT_FCE_INFO_LEN                        4
+#define MT_DMA_HDRS                    (MT_DMA_HDR_LEN + MT_RX_INFO_LEN)
+
+/* Common Tx DMA descriptor fields */
+#define MT_TXD_INFO_LEN                        GENMASK(15, 0)
+#define MT_TXD_INFO_D_PORT             GENMASK(29, 27)
+#define MT_TXD_INFO_TYPE               GENMASK(31, 30)
+
+enum mt76_msg_port {
+       WLAN_PORT,
+       CPU_RX_PORT,
+       CPU_TX_PORT,
+       HOST_PORT,
+       VIRTUAL_CPU_RX_PORT,
+       VIRTUAL_CPU_TX_PORT,
+       DISCARD,
+};
+
+enum mt76_info_type {
+       DMA_PACKET,
+       DMA_COMMAND,
+};
+
+/* Tx DMA packet specific flags */
+#define MT_TXD_PKT_INFO_NEXT_VLD       BIT(16)
+#define MT_TXD_PKT_INFO_TX_BURST       BIT(17)
+#define MT_TXD_PKT_INFO_80211          BIT(19)
+#define MT_TXD_PKT_INFO_TSO            BIT(20)
+#define MT_TXD_PKT_INFO_CSO            BIT(21)
+#define MT_TXD_PKT_INFO_WIV            BIT(24)
+#define MT_TXD_PKT_INFO_QSEL           GENMASK(26, 25)
+
+enum mt76_qsel {
+       MT_QSEL_MGMT,
+       MT_QSEL_HCCA,
+       MT_QSEL_EDCA,
+       MT_QSEL_EDCA_2,
+};
+
+/* Tx DMA MCU command specific flags */
+#define MT_TXD_CMD_INFO_SEQ            GENMASK(19, 16)
+#define MT_TXD_CMD_INFO_TYPE           GENMASK(26, 20)
+
+static inline int mt7601u_dma_skb_wrap(struct sk_buff *skb,
+                                      enum mt76_msg_port d_port,
+                                      enum mt76_info_type type, u32 flags)
+{
+       u32 info;
+
+       /* Buffer layout:
+        *      |   4B   | xfer len |      pad       |  4B  |
+        *      | TXINFO | pkt/cmd  | zero pad to 4B | zero |
+        *
+        * length field of TXINFO should be set to 'xfer len'.
+        */
+
+       info = flags |
+               MT76_SET(MT_TXD_INFO_LEN, round_up(skb->len, 4)) |
+               MT76_SET(MT_TXD_INFO_D_PORT, d_port) |
+               MT76_SET(MT_TXD_INFO_TYPE, type);
+
+       put_unaligned_le32(info, skb_push(skb, sizeof(info)));
+       return skb_put_padto(skb, round_up(skb->len, 4) + 4);
+}
+
+static inline int
+mt7601u_dma_skb_wrap_pkt(struct sk_buff *skb, enum mt76_qsel qsel, u32 flags)
+{
+       flags |= MT76_SET(MT_TXD_PKT_INFO_QSEL, qsel);
+       return mt7601u_dma_skb_wrap(skb, WLAN_PORT, DMA_PACKET, flags);
+}
+
+/* Common Rx DMA descriptor fields */
+#define MT_RXD_INFO_LEN                        GENMASK(13, 0)
+#define MT_RXD_INFO_PCIE_INTR          BIT(24)
+#define MT_RXD_INFO_QSEL               GENMASK(26, 25)
+#define MT_RXD_INFO_PORT               GENMASK(29, 27)
+#define MT_RXD_INFO_TYPE               GENMASK(31, 30)
+
+/* Rx DMA packet specific flags */
+#define MT_RXD_PKT_INFO_UDP_ERR                BIT(16)
+#define MT_RXD_PKT_INFO_TCP_ERR                BIT(17)
+#define MT_RXD_PKT_INFO_IP_ERR         BIT(18)
+#define MT_RXD_PKT_INFO_PKT_80211      BIT(19)
+#define MT_RXD_PKT_INFO_L3L4_DONE      BIT(20)
+#define MT_RXD_PKT_INFO_MAC_LEN                GENMASK(23, 21)
+
+/* Rx DMA MCU command specific flags */
+#define MT_RXD_CMD_INFO_SELF_GEN       BIT(15)
+#define MT_RXD_CMD_INFO_CMD_SEQ                GENMASK(19, 16)
+#define MT_RXD_CMD_INFO_EVT_TYPE       GENMASK(23, 20)
+
+enum mt76_evt_type {
+       CMD_DONE,
+       CMD_ERROR,
+       CMD_RETRY,
+       EVENT_PWR_RSP,
+       EVENT_WOW_RSP,
+       EVENT_CARRIER_DETECT_RSP,
+       EVENT_DFS_DETECT_RSP,
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.c b/drivers/net/wireless/mediatek/mt7601u/eeprom.c
new file mode 100644 (file)
index 0000000..ce3837f
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include <linux/of.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+#include "mt7601u.h"
+#include "eeprom.h"
+
+static bool
+field_valid(u8 val)
+{
+       return val != 0xff;
+}
+
+static s8
+field_validate(u8 val)
+{
+       if (!field_valid(val))
+               return 0;
+
+       return val;
+}
+
+static int
+mt7601u_efuse_read(struct mt7601u_dev *dev, u16 addr, u8 *data,
+                  enum mt7601u_eeprom_access_modes mode)
+{
+       u32 val;
+       int i;
+
+       val = mt76_rr(dev, MT_EFUSE_CTRL);
+       val &= ~(MT_EFUSE_CTRL_AIN |
+                MT_EFUSE_CTRL_MODE);
+       val |= MT76_SET(MT_EFUSE_CTRL_AIN, addr & ~0xf) |
+              MT76_SET(MT_EFUSE_CTRL_MODE, mode) |
+              MT_EFUSE_CTRL_KICK;
+       mt76_wr(dev, MT_EFUSE_CTRL, val);
+
+       if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
+               return -ETIMEDOUT;
+
+       val = mt76_rr(dev, MT_EFUSE_CTRL);
+       if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
+               /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0)
+                * will not return valid data but it's ok.
+                */
+               memset(data, 0xff, 16);
+               return 0;
+       }
+
+       for (i = 0; i < 4; i++) {
+               val = mt76_rr(dev, MT_EFUSE_DATA(i));
+               put_unaligned_le32(val, data + 4 * i);
+       }
+
+       return 0;
+}
+
+static int
+mt7601u_efuse_physical_size_check(struct mt7601u_dev *dev)
+{
+       const int map_reads = DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16);
+       u8 data[map_reads * 16];
+       int ret, i;
+       u32 start = 0, end = 0, cnt_free;
+
+       for (i = 0; i < map_reads; i++) {
+               ret = mt7601u_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16,
+                                        data + i * 16, MT_EE_PHYSICAL_READ);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++)
+               if (!data[i]) {
+                       if (!start)
+                               start = MT_EE_USAGE_MAP_START + i;
+                       end = MT_EE_USAGE_MAP_START + i;
+               }
+       cnt_free = end - start + 1;
+
+       if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
+               dev_err(dev->dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static bool
+mt7601u_has_tssi(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
+
+       return ~nic_conf1 && (nic_conf1 & MT_EE_NIC_CONF_1_TX_ALC_EN);
+}
+
+static void
+mt7601u_set_chip_cap(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0);
+       u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
+
+       if (!field_valid(nic_conf1 & 0xff))
+               nic_conf1 &= 0xff00;
+
+       dev->ee->tssi_enabled = mt7601u_has_tssi(dev, eeprom) &&
+                               !(nic_conf1 & MT_EE_NIC_CONF_1_TEMP_TX_ALC);
+
+       if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
+               dev_err(dev->dev,
+                       "Error: this driver does not support HW RF ctrl\n");
+
+       if (!field_valid(nic_conf0 >> 8))
+               return;
+
+       if (MT76_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 ||
+           MT76_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1)
+               dev_err(dev->dev,
+                       "Error: device has more than 1 RX/TX stream!\n");
+}
+
+static int
+mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *eeprom)
+{
+       const void *src = eeprom + MT_EE_MAC_ADDR;
+
+       ether_addr_copy(dev->macaddr, src);
+
+       if (!is_valid_ether_addr(dev->macaddr)) {
+               eth_random_addr(dev->macaddr);
+               dev_info(dev->dev,
+                        "Invalid MAC address, using random address %pM\n",
+                        dev->macaddr);
+       }
+
+       mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
+       mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
+               MT76_SET(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
+
+       return 0;
+}
+
+static void mt7601u_set_channel_target_power(struct mt7601u_dev *dev,
+                                            u8 *eeprom, u8 max_pwr)
+{
+       u8 trgt_pwr = eeprom[MT_EE_TX_TSSI_TARGET_POWER];
+
+       if (trgt_pwr > max_pwr || !trgt_pwr) {
+               dev_warn(dev->dev, "Error: EEPROM trgt power invalid %hhx!\n",
+                        trgt_pwr);
+               trgt_pwr = 0x20;
+       }
+
+       memset(dev->ee->chan_pwr, trgt_pwr, sizeof(dev->ee->chan_pwr));
+}
+
+static void
+mt7601u_set_channel_power(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       u32 i, val;
+       u8 max_pwr;
+
+       val = mt7601u_rr(dev, MT_TX_ALC_CFG_0);
+       max_pwr = MT76_GET(MT_TX_ALC_CFG_0_LIMIT_0, val);
+
+       if (mt7601u_has_tssi(dev, eeprom)) {
+               mt7601u_set_channel_target_power(dev, eeprom, max_pwr);
+               return;
+       }
+
+       for (i = 0; i < 14; i++) {
+               s8 power = field_validate(eeprom[MT_EE_TX_POWER_OFFSET + i]);
+
+               if (power > max_pwr || power < 0)
+                       power = MT7601U_DEFAULT_TX_POWER;
+
+               dev->ee->chan_pwr[i] = power;
+       }
+}
+
+static void
+mt7601u_set_country_reg(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       /* Note: - region 31 is not valid for mt7601u (see rtmp_init.c)
+        *       - comments in rtmp_def.h are incorrect (see rt_channel.c)
+        */
+       static const struct reg_channel_bounds chan_bounds[] = {
+               /* EEPROM country regions 0 - 7 */
+               {  1, 11 },     {  1, 13 },     { 10,  2 },     { 10,  4 },
+               { 14,  1 },     {  1, 14 },     {  3,  7 },     {  5,  9 },
+               /* EEPROM country regions 32 - 33 */
+               {  1, 11 },     {  1, 14 }
+       };
+       u8 val = eeprom[MT_EE_COUNTRY_REGION];
+       int idx = -1;
+
+       if (val < 8)
+               idx = val;
+       if (val > 31 && val < 33)
+               idx = val - 32 + 8;
+
+       if (idx != -1)
+               dev_info(dev->dev,
+                        "EEPROM country region %02hhx (channels %hhd-%hhd)\n",
+                        val, chan_bounds[idx].start,
+                        chan_bounds[idx].start + chan_bounds[idx].num - 1);
+       else
+               idx = 5; /* channels 1 - 14 */
+
+       dev->ee->reg = chan_bounds[idx];
+
+       /* TODO: country region 33 is special - phy should be set to B-mode
+        *       before entering channel 14 (see sta/connect.c)
+        */
+}
+
+static void
+mt7601u_set_rf_freq_off(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       u8 comp;
+
+       dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]);
+       comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]);
+
+       if (comp & BIT(7))
+               dev->ee->rf_freq_off -= comp & 0x7f;
+       else
+               dev->ee->rf_freq_off += comp;
+}
+
+static void
+mt7601u_set_rssi_offset(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       int i;
+       s8 *rssi_offset = dev->ee->rssi_offset;
+
+       for (i = 0; i < 2; i++) {
+               rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i];
+
+               if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
+                       dev_warn(dev->dev,
+                                "Warning: EEPROM RSSI is invalid %02hhx\n",
+                                rssi_offset[i]);
+                       rssi_offset[i] = 0;
+               }
+       }
+}
+
+static void
+mt7601u_extra_power_over_mac(struct mt7601u_dev *dev)
+{
+       u32 val;
+
+       val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_1) & 0x0000ff00) >> 8);
+       val |= ((mt7601u_rr(dev, MT_TX_PWR_CFG_2) & 0x0000ff00) << 8);
+       mt7601u_wr(dev, MT_TX_PWR_CFG_7, val);
+
+       val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_4) & 0x0000ff00) >> 8);
+       mt7601u_wr(dev, MT_TX_PWR_CFG_9, val);
+}
+
+static void
+mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value)
+{
+       rate->raw = s6_validate(value);
+       rate->bw20 = s6_to_int(value);
+       /* Note: vendor driver does cap the value to s6 right away */
+       rate->bw40 = rate->bw20 + delta;
+}
+
+static void
+mt7601u_save_power_rate(struct mt7601u_dev *dev, s8 delta, u32 val, int i)
+{
+       struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
+
+       switch (i) {
+       case 0:
+               mt7601u_set_power_rate(&t->cck[0], delta, (val >> 0) & 0xff);
+               mt7601u_set_power_rate(&t->cck[1], delta, (val >> 8) & 0xff);
+               /* Save cck bw20 for fixups of channel 14 */
+               dev->ee->real_cck_bw20[0] = t->cck[0].bw20;
+               dev->ee->real_cck_bw20[1] = t->cck[1].bw20;
+
+               mt7601u_set_power_rate(&t->ofdm[0], delta, (val >> 16) & 0xff);
+               mt7601u_set_power_rate(&t->ofdm[1], delta, (val >> 24) & 0xff);
+               break;
+       case 1:
+               mt7601u_set_power_rate(&t->ofdm[2], delta, (val >> 0) & 0xff);
+               mt7601u_set_power_rate(&t->ofdm[3], delta, (val >> 8) & 0xff);
+               mt7601u_set_power_rate(&t->ht[0], delta, (val >> 16) & 0xff);
+               mt7601u_set_power_rate(&t->ht[1], delta, (val >> 24) & 0xff);
+               break;
+       case 2:
+               mt7601u_set_power_rate(&t->ht[2], delta, (val >> 0) & 0xff);
+               mt7601u_set_power_rate(&t->ht[3], delta, (val >> 8) & 0xff);
+               break;
+       }
+}
+
+static s8
+get_delta(u8 val)
+{
+       s8 ret;
+
+       if (!field_valid(val) || !(val & BIT(7)))
+               return 0;
+
+       ret = val & 0x1f;
+       if (ret > 8)
+               ret = 8;
+       if (val & BIT(6))
+               ret = -ret;
+
+       return ret;
+}
+
+static void
+mt7601u_config_tx_power_per_rate(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       u32 val;
+       s8 bw40_delta;
+       int i;
+
+       bw40_delta = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]);
+
+       for (i = 0; i < 5; i++) {
+               val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i));
+
+               mt7601u_save_power_rate(dev, bw40_delta, val, i);
+
+               if (~val)
+                       mt7601u_wr(dev, MT_TX_PWR_CFG_0 + i * 4, val);
+       }
+
+       mt7601u_extra_power_over_mac(dev);
+}
+
+static void
+mt7601u_init_tssi_params(struct mt7601u_dev *dev, u8 *eeprom)
+{
+       struct tssi_data *d = &dev->ee->tssi_data;
+
+       if (!dev->ee->tssi_enabled)
+               return;
+
+       d->slope = eeprom[MT_EE_TX_TSSI_SLOPE];
+       d->tx0_delta_offset = eeprom[MT_EE_TX_TSSI_OFFSET] * 1024;
+       d->offset[0] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP];
+       d->offset[1] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 1];
+       d->offset[2] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 2];
+}
+
+int
+mt7601u_eeprom_init(struct mt7601u_dev *dev)
+{
+       u8 *eeprom;
+       int i, ret;
+
+       ret = mt7601u_efuse_physical_size_check(dev);
+       if (ret)
+               return ret;
+
+       dev->ee = devm_kzalloc(dev->dev, sizeof(*dev->ee), GFP_KERNEL);
+       if (!dev->ee)
+               return -ENOMEM;
+
+       eeprom = kmalloc(MT7601U_EEPROM_SIZE, GFP_KERNEL);
+       if (!eeprom)
+               return -ENOMEM;
+
+       for (i = 0; i + 16 <= MT7601U_EEPROM_SIZE; i += 16) {
+               ret = mt7601u_efuse_read(dev, i, eeprom + i, MT_EE_READ);
+               if (ret)
+                       goto out;
+       }
+
+       if (eeprom[MT_EE_VERSION_EE] > MT7601U_EE_MAX_VER)
+               dev_warn(dev->dev,
+                        "Warning: unsupported EEPROM version %02hhx\n",
+                        eeprom[MT_EE_VERSION_EE]);
+       dev_info(dev->dev, "EEPROM ver:%02hhx fae:%02hhx\n",
+                eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
+
+       mt7601u_set_macaddr(dev, eeprom);
+       mt7601u_set_chip_cap(dev, eeprom);
+       mt7601u_set_channel_power(dev, eeprom);
+       mt7601u_set_country_reg(dev, eeprom);
+       mt7601u_set_rf_freq_off(dev, eeprom);
+       mt7601u_set_rssi_offset(dev, eeprom);
+       dev->ee->ref_temp = eeprom[MT_EE_REF_TEMP];
+       dev->ee->lna_gain = eeprom[MT_EE_LNA_GAIN];
+
+       mt7601u_config_tx_power_per_rate(dev, eeprom);
+
+       mt7601u_init_tssi_params(dev, eeprom);
+out:
+       kfree(eeprom);
+       return ret;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.h b/drivers/net/wireless/mediatek/mt7601u/eeprom.h
new file mode 100644 (file)
index 0000000..662d127
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_EEPROM_H
+#define __MT7601U_EEPROM_H
+
+struct mt7601u_dev;
+
+#define MT7601U_EE_MAX_VER                     0x0c
+#define MT7601U_EEPROM_SIZE                    256
+
+#define MT7601U_DEFAULT_TX_POWER               6
+
+enum mt76_eeprom_field {
+       MT_EE_CHIP_ID =                         0x00,
+       MT_EE_VERSION_FAE =                     0x02,
+       MT_EE_VERSION_EE =                      0x03,
+       MT_EE_MAC_ADDR =                        0x04,
+       MT_EE_NIC_CONF_0 =                      0x34,
+       MT_EE_NIC_CONF_1 =                      0x36,
+       MT_EE_COUNTRY_REGION =                  0x39,
+       MT_EE_FREQ_OFFSET =                     0x3a,
+       MT_EE_NIC_CONF_2 =                      0x42,
+
+       MT_EE_LNA_GAIN =                        0x44,
+       MT_EE_RSSI_OFFSET =                     0x46,
+
+       MT_EE_TX_POWER_DELTA_BW40 =             0x50,
+       MT_EE_TX_POWER_OFFSET =                 0x52,
+
+       MT_EE_TX_TSSI_SLOPE =                   0x6e,
+       MT_EE_TX_TSSI_OFFSET_GROUP =            0x6f,
+       MT_EE_TX_TSSI_OFFSET =                  0x76,
+
+       MT_EE_TX_TSSI_TARGET_POWER =            0xd0,
+       MT_EE_REF_TEMP =                        0xd1,
+       MT_EE_FREQ_OFFSET_COMPENSATION =        0xdb,
+       MT_EE_TX_POWER_BYRATE_BASE =            0xde,
+
+       MT_EE_USAGE_MAP_START =                 0x1e0,
+       MT_EE_USAGE_MAP_END =                   0x1fc,
+};
+
+#define MT_EE_NIC_CONF_0_RX_PATH               GENMASK(3, 0)
+#define MT_EE_NIC_CONF_0_TX_PATH               GENMASK(7, 4)
+#define MT_EE_NIC_CONF_0_BOARD_TYPE            GENMASK(13, 12)
+
+#define MT_EE_NIC_CONF_1_HW_RF_CTRL            BIT(0)
+#define MT_EE_NIC_CONF_1_TEMP_TX_ALC           BIT(1)
+#define MT_EE_NIC_CONF_1_LNA_EXT_2G            BIT(2)
+#define MT_EE_NIC_CONF_1_LNA_EXT_5G            BIT(3)
+#define MT_EE_NIC_CONF_1_TX_ALC_EN             BIT(13)
+
+#define MT_EE_NIC_CONF_2_RX_STREAM             GENMASK(3, 0)
+#define MT_EE_NIC_CONF_2_TX_STREAM             GENMASK(7, 4)
+#define MT_EE_NIC_CONF_2_HW_ANTDIV             BIT(8)
+#define MT_EE_NIC_CONF_2_XTAL_OPTION           GENMASK(10, 9)
+#define MT_EE_NIC_CONF_2_TEMP_DISABLE          BIT(11)
+#define MT_EE_NIC_CONF_2_COEX_METHOD           GENMASK(15, 13)
+
+#define MT_EE_TX_POWER_BYRATE(i)               (MT_EE_TX_POWER_BYRATE_BASE + \
+                                                (i) * 4)
+
+#define MT_EFUSE_USAGE_MAP_SIZE                        (MT_EE_USAGE_MAP_END -  \
+                                                MT_EE_USAGE_MAP_START + 1)
+
+enum mt7601u_eeprom_access_modes {
+       MT_EE_READ = 0,
+       MT_EE_PHYSICAL_READ = 1,
+};
+
+struct power_per_rate  {
+       u8 raw;  /* validated s6 value */
+       s8 bw20; /* sign-extended int */
+       s8 bw40; /* sign-extended int */
+};
+
+/* Power per rate - one value per two rates */
+struct mt7601u_rate_power {
+       struct power_per_rate cck[2];
+       struct power_per_rate ofdm[4];
+       struct power_per_rate ht[4];
+};
+
+struct reg_channel_bounds {
+       u8 start;
+       u8 num;
+};
+
+struct mt7601u_eeprom_params {
+       bool tssi_enabled;
+       u8 rf_freq_off;
+       s8 rssi_offset[2];
+       s8 ref_temp;
+       s8 lna_gain;
+
+       u8 chan_pwr[14];
+       struct mt7601u_rate_power power_rate_table;
+       s8 real_cck_bw20[2];
+
+       /* TSSI stuff - only with internal TX ALC */
+       struct tssi_data {
+               int tx0_delta_offset;
+               u8 slope;
+               u8 offset[3];
+       } tssi_data;
+
+       struct reg_channel_bounds reg;
+};
+
+int mt7601u_eeprom_init(struct mt7601u_dev *dev);
+
+static inline u32 s6_validate(u32 reg)
+{
+       WARN_ON(reg & ~GENMASK(5, 0));
+       return reg & GENMASK(5, 0);
+}
+
+static inline int s6_to_int(u32 reg)
+{
+       int s6;
+
+       s6 = s6_validate(reg);
+       if (s6 & BIT(5))
+               s6 -= BIT(6);
+
+       return s6;
+}
+
+static inline u32 int_to_s6(int val)
+{
+       if (val < -0x20)
+               return 0x20;
+       if (val > 0x1f)
+               return 0x1f;
+
+       return val & 0x3f;
+}
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c
new file mode 100644 (file)
index 0000000..1fc86e8
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * (c) Copyright 2002-2010, Ralink Technology, Inc.
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "eeprom.h"
+#include "trace.h"
+#include "mcu.h"
+
+#include "initvals.h"
+
+static void
+mt7601u_set_wlan_state(struct mt7601u_dev *dev, u32 val, bool enable)
+{
+       int i;
+
+       /* Note: we don't turn off WLAN_CLK because that makes the device
+        *       not respond properly on the probe path.
+        *       In case anyone (PSM?) wants to use this function we can
+        *       bring the clock stuff back and fixup the probe path.
+        */
+
+       if (enable)
+               val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
+                       MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
+       else
+               val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
+
+       mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
+       udelay(20);
+
+       if (enable) {
+               set_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
+       } else {
+               clear_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
+               return;
+       }
+
+       for (i = 200; i; i--) {
+               val = mt7601u_rr(dev, MT_CMB_CTRL);
+
+               if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
+                       break;
+
+               udelay(20);
+       }
+
+       /* Note: vendor driver tries to disable/enable wlan here and retry
+        *       but the code which does it is so buggy it must have never
+        *       triggered, so don't bother.
+        */
+       if (!i)
+               dev_err(dev->dev, "Error: PLL and XTAL check failed!\n");
+}
+
+static void mt7601u_chip_onoff(struct mt7601u_dev *dev, bool enable, bool reset)
+{
+       u32 val;
+
+       mutex_lock(&dev->hw_atomic_mutex);
+
+       val = mt7601u_rr(dev, MT_WLAN_FUN_CTRL);
+
+       if (reset) {
+               val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
+               val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
+
+               if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
+                       val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
+                               MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
+                       mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
+                       udelay(20);
+
+                       val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
+                                MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
+               }
+       }
+
+       mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
+       udelay(20);
+
+       mt7601u_set_wlan_state(dev, val, enable);
+
+       mutex_unlock(&dev->hw_atomic_mutex);
+}
+
+static void mt7601u_reset_csr_bbp(struct mt7601u_dev *dev)
+{
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, (MT_MAC_SYS_CTRL_RESET_CSR |
+                                         MT_MAC_SYS_CTRL_RESET_BBP));
+       mt7601u_wr(dev, MT_USB_DMA_CFG, 0);
+       msleep(1);
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
+}
+
+static void mt7601u_init_usb_dma(struct mt7601u_dev *dev)
+{
+       u32 val;
+
+       val = MT76_SET(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, MT_USB_AGGR_TIMEOUT) |
+             MT76_SET(MT_USB_DMA_CFG_RX_BULK_AGG_LMT, MT_USB_AGGR_SIZE_LIMIT) |
+             MT_USB_DMA_CFG_RX_BULK_EN |
+             MT_USB_DMA_CFG_TX_BULK_EN;
+       if (dev->in_max_packet == 512)
+               val |= MT_USB_DMA_CFG_RX_BULK_AGG_EN;
+       mt7601u_wr(dev, MT_USB_DMA_CFG, val);
+
+       val |= MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
+       mt7601u_wr(dev, MT_USB_DMA_CFG, val);
+       val &= ~MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
+       mt7601u_wr(dev, MT_USB_DMA_CFG, val);
+}
+
+static int mt7601u_init_bbp(struct mt7601u_dev *dev)
+{
+       int ret;
+
+       ret = mt7601u_wait_bbp_ready(dev);
+       if (ret)
+               return ret;
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_common_vals,
+                                     ARRAY_SIZE(bbp_common_vals));
+       if (ret)
+               return ret;
+
+       return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_chip_vals,
+                                      ARRAY_SIZE(bbp_chip_vals));
+}
+
+static void
+mt76_init_beacon_offsets(struct mt7601u_dev *dev)
+{
+       u16 base = MT_BEACON_BASE;
+       u32 regs[4] = {};
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               u16 addr = dev->beacon_offsets[i];
+
+               regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
+       }
+
+       for (i = 0; i < 4; i++)
+               mt7601u_wr(dev, MT_BCN_OFFSET(i), regs[i]);
+}
+
+static int mt7601u_write_mac_initvals(struct mt7601u_dev *dev)
+{
+       int ret;
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN, mac_common_vals,
+                                     ARRAY_SIZE(mac_common_vals));
+       if (ret)
+               return ret;
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN,
+                                     mac_chip_vals, ARRAY_SIZE(mac_chip_vals));
+       if (ret)
+               return ret;
+
+       mt76_init_beacon_offsets(dev);
+
+       mt7601u_wr(dev, MT_AUX_CLK_CFG, 0);
+
+       return 0;
+}
+
+static int mt7601u_init_wcid_mem(struct mt7601u_dev *dev)
+{
+       u32 *vals;
+       int i, ret;
+
+       vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
+       if (!vals)
+               return -ENOMEM;
+
+       for (i = 0; i < N_WCIDS; i++)  {
+               vals[i * 2] = 0xffffffff;
+               vals[i * 2 + 1] = 0x00ffffff;
+       }
+
+       ret = mt7601u_burst_write_regs(dev, MT_WCID_ADDR_BASE,
+                                      vals, N_WCIDS * 2);
+       kfree(vals);
+
+       return ret;
+}
+
+static int mt7601u_init_key_mem(struct mt7601u_dev *dev)
+{
+       u32 vals[4] = {};
+
+       return mt7601u_burst_write_regs(dev, MT_SKEY_MODE_BASE_0,
+                                       vals, ARRAY_SIZE(vals));
+}
+
+static int mt7601u_init_wcid_attr_mem(struct mt7601u_dev *dev)
+{
+       u32 *vals;
+       int i, ret;
+
+       vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
+       if (!vals)
+               return -ENOMEM;
+
+       for (i = 0; i < N_WCIDS * 2; i++)
+               vals[i] = 1;
+
+       ret = mt7601u_burst_write_regs(dev, MT_WCID_ATTR_BASE,
+                                      vals, N_WCIDS * 2);
+       kfree(vals);
+
+       return ret;
+}
+
+static void mt7601u_reset_counters(struct mt7601u_dev *dev)
+{
+       mt7601u_rr(dev, MT_RX_STA_CNT0);
+       mt7601u_rr(dev, MT_RX_STA_CNT1);
+       mt7601u_rr(dev, MT_RX_STA_CNT2);
+       mt7601u_rr(dev, MT_TX_STA_CNT0);
+       mt7601u_rr(dev, MT_TX_STA_CNT1);
+       mt7601u_rr(dev, MT_TX_STA_CNT2);
+}
+
+int mt7601u_mac_start(struct mt7601u_dev *dev)
+{
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
+
+       if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+                      MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
+               return -ETIMEDOUT;
+
+       dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
+               MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
+               MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
+               MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
+               MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
+               MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
+               MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
+       mt7601u_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
+
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL,
+                  MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+
+       if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+                      MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev)
+{
+       int i, ok;
+
+       if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return;
+
+       mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
+                  MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
+                  MT_BEACON_TIME_CFG_BEACON_TX);
+
+       if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
+               dev_warn(dev->dev, "Warning: TX DMA did not stop!\n");
+
+       /* Page count on TxQ */
+       i = 200;
+       while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
+                      (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
+                      (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
+               msleep(10);
+
+       if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
+               dev_warn(dev->dev, "Warning: MAC TX did not stop!\n");
+
+       mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
+                                        MT_MAC_SYS_CTRL_ENABLE_TX);
+
+       /* Page count on RxQ */
+       ok = 0;
+       i = 200;
+       while (i--) {
+               if ((mt76_rr(dev, 0x0430) & 0x00ff0000) ||
+                   (mt76_rr(dev, 0x0a30) & 0xffffffff) ||
+                   (mt76_rr(dev, 0x0a34) & 0xffffffff))
+                       ok++;
+               if (ok > 6)
+                       break;
+
+               msleep(1);
+       }
+
+       if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
+               dev_warn(dev->dev, "Warning: MAC RX did not stop!\n");
+
+       if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
+               dev_warn(dev->dev, "Warning: RX DMA did not stop!\n");
+}
+
+void mt7601u_mac_stop(struct mt7601u_dev *dev)
+{
+       mt7601u_mac_stop_hw(dev);
+       flush_delayed_work(&dev->stat_work);
+       cancel_delayed_work_sync(&dev->stat_work);
+}
+
+static void mt7601u_stop_hardware(struct mt7601u_dev *dev)
+{
+       mt7601u_chip_onoff(dev, false, false);
+}
+
+int mt7601u_init_hardware(struct mt7601u_dev *dev)
+{
+       static const u16 beacon_offsets[16] = {
+               /* 512 byte per beacon */
+               0xc000, 0xc200, 0xc400, 0xc600,
+               0xc800, 0xca00, 0xcc00, 0xce00,
+               0xd000, 0xd200, 0xd400, 0xd600,
+               0xd800, 0xda00, 0xdc00, 0xde00
+       };
+       int ret;
+
+       dev->beacon_offsets = beacon_offsets;
+
+       mt7601u_chip_onoff(dev, true, false);
+
+       ret = mt7601u_wait_asic_ready(dev);
+       if (ret)
+               goto err;
+       ret = mt7601u_mcu_init(dev);
+       if (ret)
+               goto err;
+
+       if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
+                           MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+                           MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) {
+               ret = -EIO;
+               goto err;
+       }
+
+       /* Wait for ASIC ready after FW load. */
+       ret = mt7601u_wait_asic_ready(dev);
+       if (ret)
+               goto err;
+
+       mt7601u_reset_csr_bbp(dev);
+       mt7601u_init_usb_dma(dev);
+
+       ret = mt7601u_mcu_cmd_init(dev);
+       if (ret)
+               goto err;
+       ret = mt7601u_dma_init(dev);
+       if (ret)
+               goto err_mcu;
+       ret = mt7601u_write_mac_initvals(dev);
+       if (ret)
+               goto err_rx;
+
+       if (!mt76_poll_msec(dev, MT_MAC_STATUS,
+                           MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 100)) {
+               ret = -EIO;
+               goto err_rx;
+       }
+
+       ret = mt7601u_init_bbp(dev);
+       if (ret)
+               goto err_rx;
+       ret = mt7601u_init_wcid_mem(dev);
+       if (ret)
+               goto err_rx;
+       ret = mt7601u_init_key_mem(dev);
+       if (ret)
+               goto err_rx;
+       ret = mt7601u_init_wcid_attr_mem(dev);
+       if (ret)
+               goto err_rx;
+
+       mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
+                                            MT_BEACON_TIME_CFG_SYNC_MODE |
+                                            MT_BEACON_TIME_CFG_TBTT_EN |
+                                            MT_BEACON_TIME_CFG_BEACON_TX));
+
+       mt7601u_reset_counters(dev);
+
+       mt7601u_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
+
+       mt7601u_wr(dev, MT_TXOP_CTRL_CFG, MT76_SET(MT_TXOP_TRUN_EN, 0x3f) |
+                                         MT76_SET(MT_TXOP_EXT_CCA_DLY, 0x58));
+
+       ret = mt7601u_eeprom_init(dev);
+       if (ret)
+               goto err_rx;
+
+       ret = mt7601u_phy_init(dev);
+       if (ret)
+               goto err_rx;
+
+       mt7601u_set_rx_path(dev, 0);
+       mt7601u_set_tx_dac(dev, 0);
+
+       mt7601u_mac_set_ctrlch(dev, false);
+       mt7601u_bbp_set_ctrlch(dev, false);
+       mt7601u_bbp_set_bw(dev, MT_BW_20);
+
+       return 0;
+
+err_rx:
+       mt7601u_dma_cleanup(dev);
+err_mcu:
+       mt7601u_mcu_cmd_deinit(dev);
+err:
+       mt7601u_chip_onoff(dev, false, false);
+       return ret;
+}
+
+void mt7601u_cleanup(struct mt7601u_dev *dev)
+{
+       mt7601u_stop_hardware(dev);
+       mt7601u_dma_cleanup(dev);
+       mt7601u_mcu_cmd_deinit(dev);
+}
+
+struct mt7601u_dev *mt7601u_alloc_device(struct device *pdev)
+{
+       struct ieee80211_hw *hw;
+       struct mt7601u_dev *dev;
+
+       hw = ieee80211_alloc_hw(sizeof(*dev), &mt7601u_ops);
+       if (!hw)
+               return NULL;
+
+       dev = hw->priv;
+       dev->dev = pdev;
+       dev->hw = hw;
+       mutex_init(&dev->vendor_req_mutex);
+       mutex_init(&dev->reg_atomic_mutex);
+       mutex_init(&dev->hw_atomic_mutex);
+       mutex_init(&dev->mutex);
+       spin_lock_init(&dev->tx_lock);
+       spin_lock_init(&dev->rx_lock);
+       spin_lock_init(&dev->lock);
+       spin_lock_init(&dev->con_mon_lock);
+       atomic_set(&dev->avg_ampdu_len, 1);
+
+       dev->stat_wq = alloc_workqueue("mt7601u", WQ_UNBOUND, 0);
+       if (!dev->stat_wq) {
+               ieee80211_free_hw(hw);
+               return NULL;
+       }
+
+       return dev;
+}
+
+#define CHAN2G(_idx, _freq) {                  \
+       .band = IEEE80211_BAND_2GHZ,            \
+       .center_freq = (_freq),                 \
+       .hw_value = (_idx),                     \
+       .max_power = 30,                        \
+}
+
+static const struct ieee80211_channel mt76_channels_2ghz[] = {
+       CHAN2G(1, 2412),
+       CHAN2G(2, 2417),
+       CHAN2G(3, 2422),
+       CHAN2G(4, 2427),
+       CHAN2G(5, 2432),
+       CHAN2G(6, 2437),
+       CHAN2G(7, 2442),
+       CHAN2G(8, 2447),
+       CHAN2G(9, 2452),
+       CHAN2G(10, 2457),
+       CHAN2G(11, 2462),
+       CHAN2G(12, 2467),
+       CHAN2G(13, 2472),
+       CHAN2G(14, 2484),
+};
+
+#define CCK_RATE(_idx, _rate) {                                        \
+       .bitrate = _rate,                                       \
+       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                 \
+       .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,              \
+       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),  \
+}
+
+#define OFDM_RATE(_idx, _rate) {                               \
+       .bitrate = _rate,                                       \
+       .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx,             \
+       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,       \
+}
+
+static struct ieee80211_rate mt76_rates[] = {
+       CCK_RATE(0, 10),
+       CCK_RATE(1, 20),
+       CCK_RATE(2, 55),
+       CCK_RATE(3, 110),
+       OFDM_RATE(0, 60),
+       OFDM_RATE(1, 90),
+       OFDM_RATE(2, 120),
+       OFDM_RATE(3, 180),
+       OFDM_RATE(4, 240),
+       OFDM_RATE(5, 360),
+       OFDM_RATE(6, 480),
+       OFDM_RATE(7, 540),
+};
+
+static int
+mt76_init_sband(struct mt7601u_dev *dev, struct ieee80211_supported_band *sband,
+               const struct ieee80211_channel *chan, int n_chan,
+               struct ieee80211_rate *rates, int n_rates)
+{
+       struct ieee80211_sta_ht_cap *ht_cap;
+       void *chanlist;
+       int size;
+
+       size = n_chan * sizeof(*chan);
+       chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL);
+       if (!chanlist)
+               return -ENOMEM;
+
+       sband->channels = chanlist;
+       sband->n_channels = n_chan;
+       sband->bitrates = rates;
+       sband->n_bitrates = n_rates;
+
+       ht_cap = &sband->ht_cap;
+       ht_cap->ht_supported = true;
+       ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                     IEEE80211_HT_CAP_GRN_FLD |
+                     IEEE80211_HT_CAP_SGI_20 |
+                     IEEE80211_HT_CAP_SGI_40 |
+                     (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+
+       ht_cap->mcs.rx_mask[0] = 0xff;
+       ht_cap->mcs.rx_mask[4] = 0x1;
+       ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+       ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+       ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_2;
+
+       dev->chandef.chan = &sband->channels[0];
+
+       return 0;
+}
+
+static int
+mt76_init_sband_2g(struct mt7601u_dev *dev)
+{
+       dev->sband_2g = devm_kzalloc(dev->dev, sizeof(*dev->sband_2g),
+                                    GFP_KERNEL);
+       dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = dev->sband_2g;
+
+       WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num >
+               ARRAY_SIZE(mt76_channels_2ghz));
+
+       return mt76_init_sband(dev, dev->sband_2g,
+                              &mt76_channels_2ghz[dev->ee->reg.start - 1],
+                              dev->ee->reg.num,
+                              mt76_rates, ARRAY_SIZE(mt76_rates));
+}
+
+int mt7601u_register_device(struct mt7601u_dev *dev)
+{
+       struct ieee80211_hw *hw = dev->hw;
+       struct wiphy *wiphy = hw->wiphy;
+       int ret;
+
+       /* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
+        * entry no. 1 like it does in the vendor driver.
+        */
+       dev->wcid_mask[0] |= 1;
+
+       /* init fake wcid for monitor interfaces */
+       dev->mon_wcid = devm_kmalloc(dev->dev, sizeof(*dev->mon_wcid),
+                                    GFP_KERNEL);
+       if (!dev->mon_wcid)
+               return -ENOMEM;
+       dev->mon_wcid->idx = 0xff;
+       dev->mon_wcid->hw_key_idx = -1;
+
+       SET_IEEE80211_DEV(hw, dev->dev);
+
+       hw->queues = 4;
+       hw->flags = IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_PS_NULLFUNC_STACK |
+                   IEEE80211_HW_SUPPORTS_HT_CCK_RATES |
+                   IEEE80211_HW_AMPDU_AGGREGATION |
+                   IEEE80211_HW_SUPPORTS_RC_TABLE;
+       hw->max_rates = 1;
+       hw->max_report_rates = 7;
+       hw->max_rate_tries = 1;
+
+       hw->sta_data_size = sizeof(struct mt76_sta);
+       hw->vif_data_size = sizeof(struct mt76_vif);
+
+       SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
+
+       wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+       ret = mt76_init_sband_2g(dev);
+       if (ret)
+               return ret;
+
+       INIT_DELAYED_WORK(&dev->mac_work, mt7601u_mac_work);
+       INIT_DELAYED_WORK(&dev->stat_work, mt7601u_tx_stat);
+
+       ret = ieee80211_register_hw(hw);
+       if (ret)
+               return ret;
+
+       mt7601u_init_debugfs(dev);
+
+       return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/initvals.h b/drivers/net/wireless/mediatek/mt7601u/initvals.h
new file mode 100644 (file)
index 0000000..ec11ff6
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * (c) Copyright 2002-2010, Ralink Technology, Inc.
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_INITVALS_H
+#define __MT7601U_INITVALS_H
+
+static const struct mt76_reg_pair bbp_common_vals[] = {
+       {  65,  0x2c },
+       {  66,  0x38 },
+       {  68,  0x0b },
+       {  69,  0x12 },
+       {  70,  0x0a },
+       {  73,  0x10 },
+       {  81,  0x37 },
+       {  82,  0x62 },
+       {  83,  0x6a },
+       {  84,  0x99 },
+       {  86,  0x00 },
+       {  91,  0x04 },
+       {  92,  0x00 },
+       { 103,  0x00 },
+       { 105,  0x05 },
+       { 106,  0x35 },
+};
+
+static const struct mt76_reg_pair bbp_chip_vals[] = {
+       {   1, 0x04 },  {   4, 0x40 },  {  20, 0x06 },  {  31, 0x08 },
+       /* CCK Tx Control */
+       { 178, 0xff },
+       /* AGC/Sync controls */
+       {  66, 0x14 },  {  68, 0x8b },  {  69, 0x12 },  {  70, 0x09 },
+       {  73, 0x11 },  {  75, 0x60 },  {  76, 0x44 },  {  84, 0x9a },
+       {  86, 0x38 },  {  91, 0x07 },  {  92, 0x02 },
+       /* Rx Path Controls */
+       {  99, 0x50 },  { 101, 0x00 },  { 103, 0xc0 },  { 104, 0x92 },
+       { 105, 0x3c },  { 106, 0x03 },  { 128, 0x12 },
+       /* Change RXWI content: Gain Report */
+       { 142, 0x04 },  { 143, 0x37 },
+       /* Change RXWI content: Antenna Report */
+       { 142, 0x03 },  { 143, 0x99 },
+       /* Calibration Index Register */
+       /* CCK Receiver Control */
+       { 160, 0xeb },  { 161, 0xc4 },  { 162, 0x77 },  { 163, 0xf9 },
+       { 164, 0x88 },  { 165, 0x80 },  { 166, 0xff },  { 167, 0xe4 },
+       /* Added AGC controls - these AGC/GLRT registers are accessed
+        * through R195 and R196.
+        */
+       { 195, 0x00 },  { 196, 0x00 },
+       { 195, 0x01 },  { 196, 0x04 },
+       { 195, 0x02 },  { 196, 0x20 },
+       { 195, 0x03 },  { 196, 0x0a },
+       { 195, 0x06 },  { 196, 0x16 },
+       { 195, 0x07 },  { 196, 0x05 },
+       { 195, 0x08 },  { 196, 0x37 },
+       { 195, 0x0a },  { 196, 0x15 },
+       { 195, 0x0b },  { 196, 0x17 },
+       { 195, 0x0c },  { 196, 0x06 },
+       { 195, 0x0d },  { 196, 0x09 },
+       { 195, 0x0e },  { 196, 0x05 },
+       { 195, 0x0f },  { 196, 0x09 },
+       { 195, 0x10 },  { 196, 0x20 },
+       { 195, 0x20 },  { 196, 0x17 },
+       { 195, 0x21 },  { 196, 0x06 },
+       { 195, 0x22 },  { 196, 0x09 },
+       { 195, 0x23 },  { 196, 0x17 },
+       { 195, 0x24 },  { 196, 0x06 },
+       { 195, 0x25 },  { 196, 0x09 },
+       { 195, 0x26 },  { 196, 0x17 },
+       { 195, 0x27 },  { 196, 0x06 },
+       { 195, 0x28 },  { 196, 0x09 },
+       { 195, 0x29 },  { 196, 0x05 },
+       { 195, 0x2a },  { 196, 0x09 },
+       { 195, 0x80 },  { 196, 0x8b },
+       { 195, 0x81 },  { 196, 0x12 },
+       { 195, 0x82 },  { 196, 0x09 },
+       { 195, 0x83 },  { 196, 0x17 },
+       { 195, 0x84 },  { 196, 0x11 },
+       { 195, 0x85 },  { 196, 0x00 },
+       { 195, 0x86 },  { 196, 0x00 },
+       { 195, 0x87 },  { 196, 0x18 },
+       { 195, 0x88 },  { 196, 0x60 },
+       { 195, 0x89 },  { 196, 0x44 },
+       { 195, 0x8a },  { 196, 0x8b },
+       { 195, 0x8b },  { 196, 0x8b },
+       { 195, 0x8c },  { 196, 0x8b },
+       { 195, 0x8d },  { 196, 0x8b },
+       { 195, 0x8e },  { 196, 0x09 },
+       { 195, 0x8f },  { 196, 0x09 },
+       { 195, 0x90 },  { 196, 0x09 },
+       { 195, 0x91 },  { 196, 0x09 },
+       { 195, 0x92 },  { 196, 0x11 },
+       { 195, 0x93 },  { 196, 0x11 },
+       { 195, 0x94 },  { 196, 0x11 },
+       { 195, 0x95 },  { 196, 0x11 },
+       /* PPAD */
+       {  47, 0x80 },  {  60, 0x80 },  { 150, 0xd2 },  { 151, 0x32 },
+       { 152, 0x23 },  { 153, 0x41 },  { 154, 0x00 },  { 155, 0x4f },
+       { 253, 0x7e },  { 195, 0x30 },  { 196, 0x32 },  { 195, 0x31 },
+       { 196, 0x23 },  { 195, 0x32 },  { 196, 0x45 },  { 195, 0x35 },
+       { 196, 0x4a },  { 195, 0x36 },  { 196, 0x5a },  { 195, 0x37 },
+       { 196, 0x5a },
+};
+
+static const struct mt76_reg_pair mac_common_vals[] = {
+       { MT_LEGACY_BASIC_RATE,         0x0000013f },
+       { MT_HT_BASIC_RATE,             0x00008003 },
+       { MT_MAC_SYS_CTRL,              0x00000000 },
+       { MT_RX_FILTR_CFG,              0x00017f97 },
+       { MT_BKOFF_SLOT_CFG,            0x00000209 },
+       { MT_TX_SW_CFG0,                0x00000000 },
+       { MT_TX_SW_CFG1,                0x00080606 },
+       { MT_TX_LINK_CFG,               0x00001020 },
+       { MT_TX_TIMEOUT_CFG,            0x000a2090 },
+       { MT_MAX_LEN_CFG,               0x00003fff },
+       { MT_PBF_TX_MAX_PCNT,           0x1fbf1f1f },
+       { MT_PBF_RX_MAX_PCNT,           0x0000009f },
+       { MT_TX_RETRY_CFG,              0x47d01f0f },
+       { MT_AUTO_RSP_CFG,              0x00000013 },
+       { MT_CCK_PROT_CFG,              0x05740003 },
+       { MT_OFDM_PROT_CFG,             0x05740003 },
+       { MT_MM40_PROT_CFG,             0x03f44084 },
+       { MT_GF20_PROT_CFG,             0x01744004 },
+       { MT_GF40_PROT_CFG,             0x03f44084 },
+       { MT_MM20_PROT_CFG,             0x01744004 },
+       { MT_TXOP_CTRL_CFG,             0x0000583f },
+       { MT_TX_RTS_CFG,                0x01092b20 },
+       { MT_EXP_ACK_TIME,              0x002400ca },
+       { MT_TXOP_HLDR_ET,              0x00000002 },
+       { MT_XIFS_TIME_CFG,             0x33a41010 },
+       { MT_PWR_PIN_CFG,               0x00000000 },
+};
+
+static const struct mt76_reg_pair mac_chip_vals[] = {
+       { MT_TSO_CTRL,                  0x00006050 },
+       { MT_BCN_OFFSET(0),             0x18100800 },
+       { MT_BCN_OFFSET(1),             0x38302820 },
+       { MT_PBF_SYS_CTRL,              0x00080c00 },
+       { MT_PBF_CFG,                   0x7f723c1f },
+       { MT_FCE_PSE_CTRL,              0x00000001 },
+       { MT_PAUSE_ENABLE_CONTROL1,     0x00000000 },
+       { MT_TX0_RF_GAIN_CORR,          0x003b0005 },
+       { MT_TX0_RF_GAIN_ATTEN,         0x00006900 },
+       { MT_TX0_BB_GAIN_ATTEN,         0x00000400 },
+       { MT_TX_ALC_VGA3,               0x00060006 },
+       { MT_TX_SW_CFG0,                0x00000402 },
+       { MT_TX_SW_CFG1,                0x00000000 },
+       { MT_TX_SW_CFG2,                0x00000000 },
+       { MT_HEADER_TRANS_CTRL_REG,     0x00000000 },
+       { MT_FCE_CSO,                   0x0000030f },
+       { MT_FCE_PARAMETERS,            0x00256f0f },
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/initvals_phy.h b/drivers/net/wireless/mediatek/mt7601u/initvals_phy.h
new file mode 100644 (file)
index 0000000..a2bdc3e
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * (c) Copyright 2002-2010, Ralink Technology, Inc.
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_PHY_INITVALS_H
+#define __MT7601U_PHY_INITVALS_H
+
+#define RF_REG_PAIR(bank, reg, value)                          \
+       { MT_MCU_MEMMAP_RF | (bank) << 16 | (reg), value }
+
+static const struct mt76_reg_pair rf_central[] = {
+       /* Bank 0 - for central blocks: BG, PLL, XTAL, LO, ADC/DAC */
+       RF_REG_PAIR(0,   0, 0x02),
+       RF_REG_PAIR(0,   1, 0x01),
+       RF_REG_PAIR(0,   2, 0x11),
+       RF_REG_PAIR(0,   3, 0xff),
+       RF_REG_PAIR(0,   4, 0x0a),
+       RF_REG_PAIR(0,   5, 0x20),
+       RF_REG_PAIR(0,   6, 0x00),
+       /* B/G */
+       RF_REG_PAIR(0,   7, 0x00),
+       RF_REG_PAIR(0,   8, 0x00),
+       RF_REG_PAIR(0,   9, 0x00),
+       RF_REG_PAIR(0,  10, 0x00),
+       RF_REG_PAIR(0,  11, 0x21),
+       /* XO */
+       RF_REG_PAIR(0,  13, 0x00),              /* 40mhz xtal */
+       /* RF_REG_PAIR(0,       13, 0x13), */   /* 20mhz xtal */
+       RF_REG_PAIR(0,  14, 0x7c),
+       RF_REG_PAIR(0,  15, 0x22),
+       RF_REG_PAIR(0,  16, 0x80),
+       /* PLL */
+       RF_REG_PAIR(0,  17, 0x99),
+       RF_REG_PAIR(0,  18, 0x99),
+       RF_REG_PAIR(0,  19, 0x09),
+       RF_REG_PAIR(0,  20, 0x50),
+       RF_REG_PAIR(0,  21, 0xb0),
+       RF_REG_PAIR(0,  22, 0x00),
+       RF_REG_PAIR(0,  23, 0xc5),
+       RF_REG_PAIR(0,  24, 0xfc),
+       RF_REG_PAIR(0,  25, 0x40),
+       RF_REG_PAIR(0,  26, 0x4d),
+       RF_REG_PAIR(0,  27, 0x02),
+       RF_REG_PAIR(0,  28, 0x72),
+       RF_REG_PAIR(0,  29, 0x01),
+       RF_REG_PAIR(0,  30, 0x00),
+       RF_REG_PAIR(0,  31, 0x00),
+       /* test ports */
+       RF_REG_PAIR(0,  32, 0x00),
+       RF_REG_PAIR(0,  33, 0x00),
+       RF_REG_PAIR(0,  34, 0x23),
+       RF_REG_PAIR(0,  35, 0x01), /* change setting to reduce spurs */
+       RF_REG_PAIR(0,  36, 0x00),
+       RF_REG_PAIR(0,  37, 0x00),
+       /* ADC/DAC */
+       RF_REG_PAIR(0,  38, 0x00),
+       RF_REG_PAIR(0,  39, 0x20),
+       RF_REG_PAIR(0,  40, 0x00),
+       RF_REG_PAIR(0,  41, 0xd0),
+       RF_REG_PAIR(0,  42, 0x1b),
+       RF_REG_PAIR(0,  43, 0x02),
+       RF_REG_PAIR(0,  44, 0x00),
+};
+
+static const struct mt76_reg_pair rf_channel[] = {
+       RF_REG_PAIR(4,   0, 0x01),
+       RF_REG_PAIR(4,   1, 0x00),
+       RF_REG_PAIR(4,   2, 0x00),
+       RF_REG_PAIR(4,   3, 0x00),
+       /* LDO */
+       RF_REG_PAIR(4,   4, 0x00),
+       RF_REG_PAIR(4,   5, 0x08),
+       RF_REG_PAIR(4,   6, 0x00),
+       /* RX */
+       RF_REG_PAIR(4,   7, 0x5b),
+       RF_REG_PAIR(4,   8, 0x52),
+       RF_REG_PAIR(4,   9, 0xb6),
+       RF_REG_PAIR(4,  10, 0x57),
+       RF_REG_PAIR(4,  11, 0x33),
+       RF_REG_PAIR(4,  12, 0x22),
+       RF_REG_PAIR(4,  13, 0x3d),
+       RF_REG_PAIR(4,  14, 0x3e),
+       RF_REG_PAIR(4,  15, 0x13),
+       RF_REG_PAIR(4,  16, 0x22),
+       RF_REG_PAIR(4,  17, 0x23),
+       RF_REG_PAIR(4,  18, 0x02),
+       RF_REG_PAIR(4,  19, 0xa4),
+       RF_REG_PAIR(4,  20, 0x01),
+       RF_REG_PAIR(4,  21, 0x12),
+       RF_REG_PAIR(4,  22, 0x80),
+       RF_REG_PAIR(4,  23, 0xb3),
+       RF_REG_PAIR(4,  24, 0x00), /* reserved */
+       RF_REG_PAIR(4,  25, 0x00), /* reserved */
+       RF_REG_PAIR(4,  26, 0x00), /* reserved */
+       RF_REG_PAIR(4,  27, 0x00), /* reserved */
+       /* LOGEN */
+       RF_REG_PAIR(4,  28, 0x18),
+       RF_REG_PAIR(4,  29, 0xee),
+       RF_REG_PAIR(4,  30, 0x6b),
+       RF_REG_PAIR(4,  31, 0x31),
+       RF_REG_PAIR(4,  32, 0x5d),
+       RF_REG_PAIR(4,  33, 0x00), /* reserved */
+       /* TX */
+       RF_REG_PAIR(4,  34, 0x96),
+       RF_REG_PAIR(4,  35, 0x55),
+       RF_REG_PAIR(4,  36, 0x08),
+       RF_REG_PAIR(4,  37, 0xbb),
+       RF_REG_PAIR(4,  38, 0xb3),
+       RF_REG_PAIR(4,  39, 0xb3),
+       RF_REG_PAIR(4,  40, 0x03),
+       RF_REG_PAIR(4,  41, 0x00), /* reserved */
+       RF_REG_PAIR(4,  42, 0x00), /* reserved */
+       RF_REG_PAIR(4,  43, 0xc5),
+       RF_REG_PAIR(4,  44, 0xc5),
+       RF_REG_PAIR(4,  45, 0xc5),
+       RF_REG_PAIR(4,  46, 0x07),
+       RF_REG_PAIR(4,  47, 0xa8),
+       RF_REG_PAIR(4,  48, 0xef),
+       RF_REG_PAIR(4,  49, 0x1a),
+       /* PA */
+       RF_REG_PAIR(4,  54, 0x07),
+       RF_REG_PAIR(4,  55, 0xa7),
+       RF_REG_PAIR(4,  56, 0xcc),
+       RF_REG_PAIR(4,  57, 0x14),
+       RF_REG_PAIR(4,  58, 0x07),
+       RF_REG_PAIR(4,  59, 0xa8),
+       RF_REG_PAIR(4,  60, 0xd7),
+       RF_REG_PAIR(4,  61, 0x10),
+       RF_REG_PAIR(4,  62, 0x1c),
+       RF_REG_PAIR(4,  63, 0x00), /* reserved */
+};
+
+static const struct mt76_reg_pair rf_vga[] = {
+       RF_REG_PAIR(5,   0, 0x47),
+       RF_REG_PAIR(5,   1, 0x00),
+       RF_REG_PAIR(5,   2, 0x00),
+       RF_REG_PAIR(5,   3, 0x08),
+       RF_REG_PAIR(5,   4, 0x04),
+       RF_REG_PAIR(5,   5, 0x20),
+       RF_REG_PAIR(5,   6, 0x3a),
+       RF_REG_PAIR(5,   7, 0x3a),
+       RF_REG_PAIR(5,   8, 0x00),
+       RF_REG_PAIR(5,   9, 0x00),
+       RF_REG_PAIR(5,  10, 0x10),
+       RF_REG_PAIR(5,  11, 0x10),
+       RF_REG_PAIR(5,  12, 0x10),
+       RF_REG_PAIR(5,  13, 0x10),
+       RF_REG_PAIR(5,  14, 0x10),
+       RF_REG_PAIR(5,  15, 0x20),
+       RF_REG_PAIR(5,  16, 0x22),
+       RF_REG_PAIR(5,  17, 0x7c),
+       RF_REG_PAIR(5,  18, 0x00),
+       RF_REG_PAIR(5,  19, 0x00),
+       RF_REG_PAIR(5,  20, 0x00),
+       RF_REG_PAIR(5,  21, 0xf1),
+       RF_REG_PAIR(5,  22, 0x11),
+       RF_REG_PAIR(5,  23, 0x02),
+       RF_REG_PAIR(5,  24, 0x41),
+       RF_REG_PAIR(5,  25, 0x20),
+       RF_REG_PAIR(5,  26, 0x00),
+       RF_REG_PAIR(5,  27, 0xd7),
+       RF_REG_PAIR(5,  28, 0xa2),
+       RF_REG_PAIR(5,  29, 0x20),
+       RF_REG_PAIR(5,  30, 0x49),
+       RF_REG_PAIR(5,  31, 0x20),
+       RF_REG_PAIR(5,  32, 0x04),
+       RF_REG_PAIR(5,  33, 0xf1),
+       RF_REG_PAIR(5,  34, 0xa1),
+       RF_REG_PAIR(5,  35, 0x01),
+       RF_REG_PAIR(5,  41, 0x00),
+       RF_REG_PAIR(5,  42, 0x00),
+       RF_REG_PAIR(5,  43, 0x00),
+       RF_REG_PAIR(5,  44, 0x00),
+       RF_REG_PAIR(5,  45, 0x00),
+       RF_REG_PAIR(5,  46, 0x00),
+       RF_REG_PAIR(5,  47, 0x00),
+       RF_REG_PAIR(5,  48, 0x00),
+       RF_REG_PAIR(5,  49, 0x00),
+       RF_REG_PAIR(5,  50, 0x00),
+       RF_REG_PAIR(5,  51, 0x00),
+       RF_REG_PAIR(5,  52, 0x00),
+       RF_REG_PAIR(5,  53, 0x00),
+       RF_REG_PAIR(5,  54, 0x00),
+       RF_REG_PAIR(5,  55, 0x00),
+       RF_REG_PAIR(5,  56, 0x00),
+       RF_REG_PAIR(5,  57, 0x00),
+       RF_REG_PAIR(5,  58, 0x31),
+       RF_REG_PAIR(5,  59, 0x31),
+       RF_REG_PAIR(5,  60, 0x0a),
+       RF_REG_PAIR(5,  61, 0x02),
+       RF_REG_PAIR(5,  62, 0x00),
+       RF_REG_PAIR(5,  63, 0x00),
+};
+
+/* TODO: BBP178 is set to 0xff for "CCK CH14 OBW" which overrides the settings
+ *      from channel switching. Seems stupid at best.
+ */
+static const struct mt76_reg_pair bbp_high_temp[] = {
+       {  75, 0x60 },
+       {  92, 0x02 },
+       { 178, 0xff }, /* For CCK CH14 OBW */
+       { 195, 0x88 }, { 196, 0x60 },
+}, bbp_high_temp_bw20[] = {
+       {  69, 0x12 },
+       {  91, 0x07 },
+       { 195, 0x23 }, { 196, 0x17 },
+       { 195, 0x24 }, { 196, 0x06 },
+       { 195, 0x81 }, { 196, 0x12 },
+       { 195, 0x83 }, { 196, 0x17 },
+}, bbp_high_temp_bw40[] = {
+       {  69, 0x15 },
+       {  91, 0x04 },
+       { 195, 0x23 }, { 196, 0x12 },
+       { 195, 0x24 }, { 196, 0x08 },
+       { 195, 0x81 }, { 196, 0x15 },
+       { 195, 0x83 }, { 196, 0x16 },
+}, bbp_low_temp[] = {
+       { 178, 0xff }, /* For CCK CH14 OBW */
+}, bbp_low_temp_bw20[] = {
+       {  69, 0x12 },
+       {  75, 0x5e },
+       {  91, 0x07 },
+       {  92, 0x02 },
+       { 195, 0x23 }, { 196, 0x17 },
+       { 195, 0x24 }, { 196, 0x06 },
+       { 195, 0x81 }, { 196, 0x12 },
+       { 195, 0x83 }, { 196, 0x17 },
+       { 195, 0x88 }, { 196, 0x5e },
+}, bbp_low_temp_bw40[] = {
+       {  69, 0x15 },
+       {  75, 0x5c },
+       {  91, 0x04 },
+       {  92, 0x03 },
+       { 195, 0x23 }, { 196, 0x10 },
+       { 195, 0x24 }, { 196, 0x08 },
+       { 195, 0x81 }, { 196, 0x15 },
+       { 195, 0x83 }, { 196, 0x16 },
+       { 195, 0x88 }, { 196, 0x5b },
+}, bbp_normal_temp[] = {
+       {  75, 0x60 },
+       {  92, 0x02 },
+       { 178, 0xff }, /* For CCK CH14 OBW */
+       { 195, 0x88 }, { 196, 0x60 },
+}, bbp_normal_temp_bw20[] = {
+       {  69, 0x12 },
+       {  91, 0x07 },
+       { 195, 0x23 }, { 196, 0x17 },
+       { 195, 0x24 }, { 196, 0x06 },
+       { 195, 0x81 }, { 196, 0x12 },
+       { 195, 0x83 }, { 196, 0x17 },
+}, bbp_normal_temp_bw40[] = {
+       {  69, 0x15 },
+       {  91, 0x04 },
+       { 195, 0x23 }, { 196, 0x12 },
+       { 195, 0x24 }, { 196, 0x08 },
+       { 195, 0x81 }, { 196, 0x15 },
+       { 195, 0x83 }, { 196, 0x16 },
+};
+
+#define BBP_TABLE(arr) { arr, ARRAY_SIZE(arr), }
+
+static const struct reg_table {
+       const struct mt76_reg_pair *regs;
+       size_t n;
+} bbp_mode_table[3][3] = {
+       {
+               BBP_TABLE(bbp_normal_temp_bw20),
+               BBP_TABLE(bbp_normal_temp_bw40),
+               BBP_TABLE(bbp_normal_temp),
+       }, {
+               BBP_TABLE(bbp_high_temp_bw20),
+               BBP_TABLE(bbp_high_temp_bw40),
+               BBP_TABLE(bbp_high_temp),
+       }, {
+               BBP_TABLE(bbp_low_temp_bw20),
+               BBP_TABLE(bbp_low_temp_bw40),
+               BBP_TABLE(bbp_low_temp),
+       }
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
new file mode 100644 (file)
index 0000000..c161bcc
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "trace.h"
+#include <linux/etherdevice.h>
+
+static void
+mt76_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate)
+{
+       u8 idx = MT76_GET(MT_TXWI_RATE_MCS, rate);
+
+       txrate->idx = 0;
+       txrate->flags = 0;
+       txrate->count = 1;
+
+       switch (MT76_GET(MT_TXWI_RATE_PHY_MODE, rate)) {
+       case MT_PHY_TYPE_OFDM:
+               txrate->idx = idx + 4;
+               return;
+       case MT_PHY_TYPE_CCK:
+               if (idx >= 8)
+                       idx -= 8;
+
+               txrate->idx = idx;
+               return;
+       case MT_PHY_TYPE_HT_GF:
+               txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+               /* fall through */
+       case MT_PHY_TYPE_HT:
+               txrate->flags |= IEEE80211_TX_RC_MCS;
+               txrate->idx = idx;
+               break;
+       default:
+               WARN_ON(1);
+               return;
+       }
+
+       if (MT76_GET(MT_TXWI_RATE_BW, rate) == MT_PHY_BW_40)
+               txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+
+       if (rate & MT_TXWI_RATE_SGI)
+               txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
+}
+
+static void
+mt76_mac_fill_tx_status(struct mt7601u_dev *dev, struct ieee80211_tx_info *info,
+                       struct mt76_tx_status *st)
+{
+       struct ieee80211_tx_rate *rate = info->status.rates;
+       int cur_idx, last_rate;
+       int i;
+
+       last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
+       mt76_mac_process_tx_rate(&rate[last_rate], st->rate);
+       if (last_rate < IEEE80211_TX_MAX_RATES - 1)
+               rate[last_rate + 1].idx = -1;
+
+       cur_idx = rate[last_rate].idx + st->retry;
+       for (i = 0; i <= last_rate; i++) {
+               rate[i].flags = rate[last_rate].flags;
+               rate[i].idx = max_t(int, 0, cur_idx - i);
+               rate[i].count = 1;
+       }
+
+       if (last_rate > 0)
+               rate[last_rate - 1].count = st->retry + 1 - last_rate;
+
+       info->status.ampdu_len = 1;
+       info->status.ampdu_ack_len = st->success;
+
+       if (st->is_probe)
+               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+
+       if (st->aggr)
+               info->flags |= IEEE80211_TX_CTL_AMPDU |
+                              IEEE80211_TX_STAT_AMPDU;
+
+       if (!st->ack_req)
+               info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       else if (st->success)
+               info->flags |= IEEE80211_TX_STAT_ACK;
+}
+
+u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
+                        const struct ieee80211_tx_rate *rate, u8 *nss_val)
+{
+       u16 rateval;
+       u8 phy, rate_idx;
+       u8 nss = 1;
+       u8 bw = 0;
+
+       if (rate->flags & IEEE80211_TX_RC_MCS) {
+               rate_idx = rate->idx;
+               nss = 1 + (rate->idx >> 3);
+               phy = MT_PHY_TYPE_HT;
+               if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+                       phy = MT_PHY_TYPE_HT_GF;
+               if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       bw = 1;
+       } else {
+               const struct ieee80211_rate *r;
+               int band = dev->chandef.chan->band;
+               u16 val;
+
+               r = &dev->hw->wiphy->bands[band]->bitrates[rate->idx];
+               if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       val = r->hw_value_short;
+               else
+                       val = r->hw_value;
+
+               phy = val >> 8;
+               rate_idx = val & 0xff;
+               bw = 0;
+       }
+
+       rateval = MT76_SET(MT_RXWI_RATE_MCS, rate_idx);
+       rateval |= MT76_SET(MT_RXWI_RATE_PHY, phy);
+       rateval |= MT76_SET(MT_RXWI_RATE_BW, bw);
+       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+               rateval |= MT_RXWI_RATE_SGI;
+
+       *nss_val = nss;
+       return rateval;
+}
+
+void mt76_mac_wcid_set_rate(struct mt7601u_dev *dev, struct mt76_wcid *wcid,
+                           const struct ieee80211_tx_rate *rate)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       wcid->tx_rate = mt76_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
+       wcid->tx_rate_set = true;
+       spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+struct mt76_tx_status mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev)
+{
+       struct mt76_tx_status stat = {};
+       u32 val;
+
+       val = mt7601u_rr(dev, MT_TX_STAT_FIFO);
+       stat.valid = !!(val & MT_TX_STAT_FIFO_VALID);
+       stat.success = !!(val & MT_TX_STAT_FIFO_SUCCESS);
+       stat.aggr = !!(val & MT_TX_STAT_FIFO_AGGR);
+       stat.ack_req = !!(val & MT_TX_STAT_FIFO_ACKREQ);
+       stat.pktid = MT76_GET(MT_TX_STAT_FIFO_PID_TYPE, val);
+       stat.wcid = MT76_GET(MT_TX_STAT_FIFO_WCID, val);
+       stat.rate = MT76_GET(MT_TX_STAT_FIFO_RATE, val);
+
+       return stat;
+}
+
+void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
+{
+       struct ieee80211_tx_info info = {};
+       struct ieee80211_sta *sta = NULL;
+       struct mt76_wcid *wcid = NULL;
+       void *msta;
+
+       rcu_read_lock();
+       if (stat->wcid < ARRAY_SIZE(dev->wcid))
+               wcid = rcu_dereference(dev->wcid[stat->wcid]);
+
+       if (wcid) {
+               msta = container_of(wcid, struct mt76_sta, wcid);
+               sta = container_of(msta, struct ieee80211_sta,
+                                  drv_priv);
+       }
+
+       mt76_mac_fill_tx_status(dev, &info, stat);
+       ieee80211_tx_status_noskb(dev->hw, sta, &info);
+       rcu_read_unlock();
+}
+
+void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
+                               int ht_mode)
+{
+       int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+       bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+       u32 prot[6];
+       bool ht_rts[4] = {};
+       int i;
+
+       prot[0] = MT_PROT_NAV_SHORT |
+                 MT_PROT_TXOP_ALLOW_ALL |
+                 MT_PROT_RTS_THR_EN;
+       prot[1] = prot[0];
+       if (legacy_prot)
+               prot[1] |= MT_PROT_CTRL_CTS2SELF;
+
+       prot[2] = prot[4] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_BW20;
+       prot[3] = prot[5] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_ALL;
+
+       if (legacy_prot) {
+               prot[2] |= MT_PROT_RATE_CCK_11;
+               prot[3] |= MT_PROT_RATE_CCK_11;
+               prot[4] |= MT_PROT_RATE_CCK_11;
+               prot[5] |= MT_PROT_RATE_CCK_11;
+       } else {
+               prot[2] |= MT_PROT_RATE_OFDM_24;
+               prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
+               prot[4] |= MT_PROT_RATE_OFDM_24;
+               prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
+       }
+
+       switch (mode) {
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+               break;
+
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+               ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
+               break;
+
+       case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+               ht_rts[1] = ht_rts[3] = true;
+               break;
+
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+               ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
+               break;
+       }
+
+       if (non_gf)
+               ht_rts[2] = ht_rts[3] = true;
+
+       for (i = 0; i < 4; i++)
+               if (ht_rts[i])
+                       prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
+
+       for (i = 0; i < 6; i++)
+               mt7601u_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
+}
+
+void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb)
+{
+       if (short_preamb)
+               mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
+       else
+               mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
+}
+
+void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval)
+{
+       u32 val = mt7601u_rr(dev, MT_BEACON_TIME_CFG);
+
+       val &= ~(MT_BEACON_TIME_CFG_TIMER_EN |
+                MT_BEACON_TIME_CFG_SYNC_MODE |
+                MT_BEACON_TIME_CFG_TBTT_EN);
+
+       if (!enable) {
+               mt7601u_wr(dev, MT_BEACON_TIME_CFG, val);
+               return;
+       }
+
+       val &= ~MT_BEACON_TIME_CFG_INTVAL;
+       val |= MT76_SET(MT_BEACON_TIME_CFG_INTVAL, interval << 4) |
+               MT_BEACON_TIME_CFG_TIMER_EN |
+               MT_BEACON_TIME_CFG_SYNC_MODE |
+               MT_BEACON_TIME_CFG_TBTT_EN;
+}
+
+static void mt7601u_check_mac_err(struct mt7601u_dev *dev)
+{
+       u32 val = mt7601u_rr(dev, 0x10f4);
+
+       if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
+               return;
+
+       dev_err(dev->dev, "Error: MAC specific condition occurred\n");
+
+       mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
+       udelay(10);
+       mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
+}
+
+void mt7601u_mac_work(struct work_struct *work)
+{
+       struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
+                                              mac_work.work);
+       struct {
+               u32 addr_base;
+               u32 span;
+               u64 *stat_base;
+       } spans[] = {
+               { MT_RX_STA_CNT0,       3,      dev->stats.rx_stat },
+               { MT_TX_STA_CNT0,       3,      dev->stats.tx_stat },
+               { MT_TX_AGG_STAT,       1,      dev->stats.aggr_stat },
+               { MT_MPDU_DENSITY_CNT,  1,      dev->stats.zero_len_del },
+               { MT_TX_AGG_CNT_BASE0,  8,      &dev->stats.aggr_n[0] },
+               { MT_TX_AGG_CNT_BASE1,  8,      &dev->stats.aggr_n[16] },
+       };
+       u32 sum, n;
+       int i, j, k;
+
+       /* Note: using MCU_RANDOM_READ is actually slower then reading all the
+        *       registers by hand.  MCU takes ca. 20ms to complete read of 24
+        *       registers while reading them one by one will takes roughly
+        *       24*200us =~ 5ms.
+        */
+
+       k = 0;
+       n = 0;
+       sum = 0;
+       for (i = 0; i < ARRAY_SIZE(spans); i++)
+               for (j = 0; j < spans[i].span; j++) {
+                       u32 val = mt7601u_rr(dev, spans[i].addr_base + j * 4);
+
+                       spans[i].stat_base[j * 2] += val & 0xffff;
+                       spans[i].stat_base[j * 2 + 1] += val >> 16;
+
+                       /* Calculate average AMPDU length */
+                       if (spans[i].addr_base != MT_TX_AGG_CNT_BASE0 &&
+                           spans[i].addr_base != MT_TX_AGG_CNT_BASE1)
+                               continue;
+
+                       n += (val >> 16) + (val & 0xffff);
+                       sum += (val & 0xffff) * (1 + k * 2) +
+                               (val >> 16) * (2 + k * 2);
+                       k++;
+               }
+
+       atomic_set(&dev->avg_ampdu_len, n ? DIV_ROUND_CLOSEST(sum, n) : 1);
+
+       mt7601u_check_mac_err(dev);
+
+       ieee80211_queue_delayed_work(dev->hw, &dev->mac_work, 10 * HZ);
+}
+
+void
+mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac)
+{
+       u8 zmac[ETH_ALEN] = {};
+       u32 attr;
+
+       attr = MT76_SET(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
+              MT76_SET(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
+
+       mt76_wr(dev, MT_WCID_ATTR(idx), attr);
+
+       if (mac)
+               memcpy(zmac, mac, sizeof(zmac));
+
+       mt7601u_addr_wr(dev, MT_WCID_ADDR(idx), zmac);
+}
+
+void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev)
+{
+       struct ieee80211_sta *sta;
+       struct mt76_wcid *wcid;
+       void *msta;
+       u8 min_factor = 3;
+       int i;
+
+       rcu_read_lock();
+       for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
+               wcid = rcu_dereference(dev->wcid[i]);
+               if (!wcid)
+                       continue;
+
+               msta = container_of(wcid, struct mt76_sta, wcid);
+               sta = container_of(msta, struct ieee80211_sta, drv_priv);
+
+               min_factor = min(min_factor, sta->ht_cap.ampdu_factor);
+       }
+       rcu_read_unlock();
+
+       mt7601u_wr(dev, MT_MAX_LEN_CFG, 0xa0fff |
+                  MT76_SET(MT_MAX_LEN_CFG_AMPDU, min_factor));
+}
+
+static void
+mt76_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
+{
+       u8 idx = MT76_GET(MT_RXWI_RATE_MCS, rate);
+
+       switch (MT76_GET(MT_RXWI_RATE_PHY, rate)) {
+       case MT_PHY_TYPE_OFDM:
+               if (WARN_ON(idx >= 8))
+                       idx = 0;
+               idx += 4;
+
+               status->rate_idx = idx;
+               return;
+       case MT_PHY_TYPE_CCK:
+               if (idx >= 8) {
+                       idx -= 8;
+                       status->flag |= RX_FLAG_SHORTPRE;
+               }
+
+               if (WARN_ON(idx >= 4))
+                       idx = 0;
+
+               status->rate_idx = idx;
+               return;
+       case MT_PHY_TYPE_HT_GF:
+               status->flag |= RX_FLAG_HT_GF;
+               /* fall through */
+       case MT_PHY_TYPE_HT:
+               status->flag |= RX_FLAG_HT;
+               status->rate_idx = idx;
+               break;
+       default:
+               WARN_ON(1);
+               return;
+       }
+
+       if (rate & MT_RXWI_RATE_SGI)
+               status->flag |= RX_FLAG_SHORT_GI;
+
+       if (rate & MT_RXWI_RATE_STBC)
+               status->flag |= 1 << RX_FLAG_STBC_SHIFT;
+
+       if (rate & MT_RXWI_RATE_BW)
+               status->flag |= RX_FLAG_40MHZ;
+}
+
+static void
+mt7601u_rx_monitor_beacon(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
+                         u16 rate, int rssi)
+{
+       dev->bcn_freq_off = rxwi->freq_off;
+       dev->bcn_phy_mode = MT76_GET(MT_RXWI_RATE_PHY, rate);
+       dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
+}
+
+static int
+mt7601u_rx_is_our_beacon(struct mt7601u_dev *dev, u8 *data)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data;
+
+       return ieee80211_is_beacon(hdr->frame_control) &&
+               ether_addr_equal(hdr->addr2, dev->ap_bssid);
+}
+
+u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
+                       u8 *data, void *rxi)
+{
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+       struct mt7601u_rxwi *rxwi = rxi;
+       u32 ctl = le32_to_cpu(rxwi->ctl);
+       u16 rate = le16_to_cpu(rxwi->rate);
+       int rssi;
+
+       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
+               status->flag |= RX_FLAG_DECRYPTED;
+               status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
+       }
+
+       status->chains = BIT(0);
+       rssi = mt7601u_phy_get_rssi(dev, rxwi, rate);
+       status->chain_signal[0] = status->signal = rssi;
+       status->freq = dev->chandef.chan->center_freq;
+       status->band = dev->chandef.chan->band;
+
+       mt76_mac_process_rate(status, rate);
+
+       spin_lock_bh(&dev->con_mon_lock);
+       if (mt7601u_rx_is_our_beacon(dev, data))
+               mt7601u_rx_monitor_beacon(dev, rxwi, rate, rssi);
+       else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_U2M))
+               dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
+       spin_unlock_bh(&dev->con_mon_lock);
+
+       return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+}
+
+static enum mt76_cipher_type
+mt76_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
+{
+       memset(key_data, 0, 32);
+       if (!key)
+               return MT_CIPHER_NONE;
+
+       if (key->keylen > 32)
+               return MT_CIPHER_NONE;
+
+       memcpy(key_data, key->key, key->keylen);
+
+       switch (key->cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+               return MT_CIPHER_WEP40;
+       case WLAN_CIPHER_SUITE_WEP104:
+               return MT_CIPHER_WEP104;
+       case WLAN_CIPHER_SUITE_TKIP:
+               return MT_CIPHER_TKIP;
+       case WLAN_CIPHER_SUITE_CCMP:
+               return MT_CIPHER_AES_CCMP;
+       default:
+               return MT_CIPHER_NONE;
+       }
+}
+
+int mt76_mac_wcid_set_key(struct mt7601u_dev *dev, u8 idx,
+                         struct ieee80211_key_conf *key)
+{
+       enum mt76_cipher_type cipher;
+       u8 key_data[32];
+       u8 iv_data[8];
+       u32 val;
+
+       cipher = mt76_mac_get_key_info(key, key_data);
+       if (cipher == MT_CIPHER_NONE && key)
+               return -EINVAL;
+
+       trace_set_key(dev, idx);
+
+       mt7601u_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
+
+       memset(iv_data, 0, sizeof(iv_data));
+       if (key) {
+               iv_data[3] = key->keyidx << 6;
+               if (cipher >= MT_CIPHER_TKIP) {
+                       /* Note: start with 1 to comply with spec,
+                        *       (see comment on common/cmm_wpa.c:4291).
+                        */
+                       iv_data[0] |= 1;
+                       iv_data[3] |= 0x20;
+               }
+       }
+       mt7601u_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
+
+       val = mt7601u_rr(dev, MT_WCID_ATTR(idx));
+       val &= ~MT_WCID_ATTR_PKEY_MODE & ~MT_WCID_ATTR_PKEY_MODE_EXT;
+       val |= MT76_SET(MT_WCID_ATTR_PKEY_MODE, cipher & 7) |
+              MT76_SET(MT_WCID_ATTR_PKEY_MODE_EXT, cipher >> 3);
+       val &= ~MT_WCID_ATTR_PAIRWISE;
+       val |= MT_WCID_ATTR_PAIRWISE *
+               !!(key && key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
+       mt7601u_wr(dev, MT_WCID_ATTR(idx), val);
+
+       return 0;
+}
+
+int mt76_mac_shared_key_setup(struct mt7601u_dev *dev, u8 vif_idx, u8 key_idx,
+                             struct ieee80211_key_conf *key)
+{
+       enum mt76_cipher_type cipher;
+       u8 key_data[32];
+       u32 val;
+
+       cipher = mt76_mac_get_key_info(key, key_data);
+       if (cipher == MT_CIPHER_NONE && key)
+               return -EINVAL;
+
+       trace_set_shared_key(dev, vif_idx, key_idx);
+
+       mt7601u_wr_copy(dev, MT_SKEY(vif_idx, key_idx),
+                       key_data, sizeof(key_data));
+
+       val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
+       val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx));
+       val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx);
+       mt76_wr(dev, MT_SKEY_MODE(vif_idx), val);
+
+       return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.h b/drivers/net/wireless/mediatek/mt7601u/mac.h
new file mode 100644 (file)
index 0000000..2c22d63
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT76_MAC_H
+#define __MT76_MAC_H
+
+struct mt76_tx_status {
+       u8 valid:1;
+       u8 success:1;
+       u8 aggr:1;
+       u8 ack_req:1;
+       u8 is_probe:1;
+       u8 wcid;
+       u8 pktid;
+       u8 retry;
+       u16 rate;
+} __packed __aligned(2);
+
+/* Note: values in original "RSSI" and "SNR" fields are not actually what they
+ *      are called for MT7601U, names used by this driver are educated guesses
+ *      (see vendor mac/ral_omac.c).
+ */
+struct mt7601u_rxwi {
+       __le32 rxinfo;
+
+       __le32 ctl;
+
+       __le16 frag_sn;
+       __le16 rate;
+
+       u8 unknown;
+       u8 zero[3];
+
+       u8 snr;
+       u8 ant;
+       u8 gain;
+       u8 freq_off;
+
+       __le32 resv2;
+       __le32 expert_ant;
+} __packed __aligned(4);
+
+#define MT_RXINFO_BA                   BIT(0)
+#define MT_RXINFO_DATA                 BIT(1)
+#define MT_RXINFO_NULL                 BIT(2)
+#define MT_RXINFO_FRAG                 BIT(3)
+#define MT_RXINFO_U2M                  BIT(4)
+#define MT_RXINFO_MULTICAST            BIT(5)
+#define MT_RXINFO_BROADCAST            BIT(6)
+#define MT_RXINFO_MYBSS                        BIT(7)
+#define MT_RXINFO_CRCERR               BIT(8)
+#define MT_RXINFO_ICVERR               BIT(9)
+#define MT_RXINFO_MICERR               BIT(10)
+#define MT_RXINFO_AMSDU                        BIT(11)
+#define MT_RXINFO_HTC                  BIT(12)
+#define MT_RXINFO_RSSI                 BIT(13)
+#define MT_RXINFO_L2PAD                        BIT(14)
+#define MT_RXINFO_AMPDU                        BIT(15)
+#define MT_RXINFO_DECRYPT              BIT(16)
+#define MT_RXINFO_BSSIDX3              BIT(17)
+#define MT_RXINFO_WAPI_KEY             BIT(18)
+#define MT_RXINFO_PN_LEN               GENMASK(21, 19)
+#define MT_RXINFO_SW_PKT_80211         BIT(22)
+#define MT_RXINFO_TCP_SUM_BYPASS       BIT(28)
+#define MT_RXINFO_IP_SUM_BYPASS                BIT(29)
+#define MT_RXINFO_TCP_SUM_ERR          BIT(30)
+#define MT_RXINFO_IP_SUM_ERR           BIT(31)
+
+#define MT_RXWI_CTL_WCID               GENMASK(7, 0)
+#define MT_RXWI_CTL_KEY_IDX            GENMASK(9, 8)
+#define MT_RXWI_CTL_BSS_IDX            GENMASK(12, 10)
+#define MT_RXWI_CTL_UDF                        GENMASK(15, 13)
+#define MT_RXWI_CTL_MPDU_LEN           GENMASK(27, 16)
+#define MT_RXWI_CTL_TID                        GENMASK(31, 28)
+
+#define MT_RXWI_FRAG                   GENMASK(3, 0)
+#define MT_RXWI_SN                     GENMASK(15, 4)
+
+#define MT_RXWI_RATE_MCS               GENMASK(6, 0)
+#define MT_RXWI_RATE_BW                        BIT(7)
+#define MT_RXWI_RATE_SGI               BIT(8)
+#define MT_RXWI_RATE_STBC              GENMASK(10, 9)
+#define MT_RXWI_RATE_ETXBF             BIT(11)
+#define MT_RXWI_RATE_SND               BIT(12)
+#define MT_RXWI_RATE_ITXBF             BIT(13)
+#define MT_RXWI_RATE_PHY               GENMASK(15, 14)
+
+#define MT_RXWI_GAIN_RSSI_VAL          GENMASK(5, 0)
+#define MT_RXWI_GAIN_RSSI_LNA_ID       GENMASK(7, 6)
+#define MT_RXWI_ANT_AUX_LNA            BIT(7)
+
+#define MT_RXWI_EANT_ENC_ANT_ID                GENMASK(7, 0)
+
+enum mt76_phy_type {
+       MT_PHY_TYPE_CCK,
+       MT_PHY_TYPE_OFDM,
+       MT_PHY_TYPE_HT,
+       MT_PHY_TYPE_HT_GF,
+};
+
+enum mt76_phy_bandwidth {
+       MT_PHY_BW_20,
+       MT_PHY_BW_40,
+};
+
+struct mt76_txwi {
+       __le16 flags;
+       __le16 rate_ctl;
+
+       u8 ack_ctl;
+       u8 wcid;
+       __le16 len_ctl;
+
+       __le32 iv;
+
+       __le32 eiv;
+
+       u8 aid;
+       u8 txstream;
+       __le16 ctl;
+} __packed __aligned(4);
+
+#define MT_TXWI_FLAGS_FRAG             BIT(0)
+#define MT_TXWI_FLAGS_MMPS             BIT(1)
+#define MT_TXWI_FLAGS_CFACK            BIT(2)
+#define MT_TXWI_FLAGS_TS               BIT(3)
+#define MT_TXWI_FLAGS_AMPDU            BIT(4)
+#define MT_TXWI_FLAGS_MPDU_DENSITY     GENMASK(7, 5)
+#define MT_TXWI_FLAGS_TXOP             GENMASK(9, 8)
+#define MT_TXWI_FLAGS_CWMIN            GENMASK(12, 10)
+#define MT_TXWI_FLAGS_NO_RATE_FALLBACK BIT(13)
+#define MT_TXWI_FLAGS_TX_RPT           BIT(14)
+#define MT_TXWI_FLAGS_TX_RATE_LUT      BIT(15)
+
+#define MT_TXWI_RATE_MCS               GENMASK(6, 0)
+#define MT_TXWI_RATE_BW                        BIT(7)
+#define MT_TXWI_RATE_SGI               BIT(8)
+#define MT_TXWI_RATE_STBC              GENMASK(10, 9)
+#define MT_TXWI_RATE_PHY_MODE          GENMASK(15, 14)
+
+#define MT_TXWI_ACK_CTL_REQ            BIT(0)
+#define MT_TXWI_ACK_CTL_NSEQ           BIT(1)
+#define MT_TXWI_ACK_CTL_BA_WINDOW      GENMASK(7, 2)
+
+#define MT_TXWI_LEN_BYTE_CNT           GENMASK(11, 0)
+#define MT_TXWI_LEN_PKTID              GENMASK(15, 12)
+
+#define MT_TXWI_CTL_TX_POWER_ADJ       GENMASK(3, 0)
+#define MT_TXWI_CTL_CHAN_CHECK_PKT     BIT(4)
+#define MT_TXWI_CTL_PIFS_REV           BIT(6)
+
+u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
+                       u8 *data, void *rxi);
+int mt76_mac_wcid_set_key(struct mt7601u_dev *dev, u8 idx,
+                         struct ieee80211_key_conf *key);
+void mt76_mac_wcid_set_rate(struct mt7601u_dev *dev, struct mt76_wcid *wcid,
+                           const struct ieee80211_tx_rate *rate);
+
+int mt76_mac_shared_key_setup(struct mt7601u_dev *dev, u8 vif_idx, u8 key_idx,
+                             struct ieee80211_key_conf *key);
+u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
+                        const struct ieee80211_tx_rate *rate, u8 *nss_val);
+struct mt76_tx_status
+mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev);
+void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
new file mode 100644 (file)
index 0000000..ced82ab
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "mac.h"
+#include <linux/etherdevice.h>
+#include <linux/version.h>
+
+static int mt7601u_start(struct ieee80211_hw *hw)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       int ret;
+
+       mutex_lock(&dev->mutex);
+
+       ret = mt7601u_mac_start(dev);
+       if (ret)
+               goto out;
+
+       ieee80211_queue_delayed_work(dev->hw, &dev->mac_work,
+                                    MT_CALIBRATE_INTERVAL);
+       ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
+                                    MT_CALIBRATE_INTERVAL);
+out:
+       mutex_unlock(&dev->mutex);
+       return ret;
+}
+
+static void mt7601u_stop(struct ieee80211_hw *hw)
+{
+       struct mt7601u_dev *dev = hw->priv;
+
+       mutex_lock(&dev->mutex);
+
+       cancel_delayed_work_sync(&dev->cal_work);
+       cancel_delayed_work_sync(&dev->mac_work);
+       mt7601u_mac_stop(dev);
+
+       mutex_unlock(&dev->mutex);
+}
+
+static int mt7601u_add_interface(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
+       unsigned int idx = 0;
+       unsigned int wcid = GROUP_WCID(idx);
+
+       /* Note: for AP do the AP-STA things mt76 does:
+        *      - beacon offsets
+        *      - do mac address tricks
+        *      - shift vif idx
+        */
+       mvif->idx = idx;
+
+       if (dev->wcid_mask[wcid / BITS_PER_LONG] & BIT(wcid % BITS_PER_LONG))
+               return -ENOSPC;
+       dev->wcid_mask[wcid / BITS_PER_LONG] |= BIT(wcid % BITS_PER_LONG);
+       mvif->group_wcid.idx = wcid;
+       mvif->group_wcid.hw_key_idx = -1;
+
+       return 0;
+}
+
+static void mt7601u_remove_interface(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
+       unsigned int wcid = mvif->group_wcid.idx;
+
+       dev->wcid_mask[wcid / BITS_PER_LONG] &= ~BIT(wcid % BITS_PER_LONG);
+}
+
+static int mt7601u_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       int ret = 0;
+
+       mutex_lock(&dev->mutex);
+
+       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+               ieee80211_stop_queues(hw);
+               ret = mt7601u_phy_set_channel(dev, &hw->conf.chandef);
+               ieee80211_wake_queues(hw);
+       }
+
+       mutex_unlock(&dev->mutex);
+
+       return ret;
+}
+
+static void
+mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+                     unsigned int *total_flags, u64 multicast)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       u32 flags = 0;
+
+#define MT76_FILTER(_flag, _hw) do { \
+               flags |= *total_flags & FIF_##_flag;                    \
+               dev->rxfilter &= ~(_hw);                                \
+               dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);        \
+       } while (0)
+
+       mutex_lock(&dev->mutex);
+
+       dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
+
+       MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
+       MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
+       MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
+                            MT_RX_FILTR_CFG_CTS |
+                            MT_RX_FILTR_CFG_CFEND |
+                            MT_RX_FILTR_CFG_CFACK |
+                            MT_RX_FILTR_CFG_BA |
+                            MT_RX_FILTR_CFG_CTRL_RSV);
+       MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL);
+
+       *total_flags = flags;
+       mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
+
+       mutex_unlock(&dev->mutex);
+}
+
+static void
+mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_bss_conf *info, u32 changed)
+{
+       struct mt7601u_dev *dev = hw->priv;
+
+       mutex_lock(&dev->mutex);
+
+       if (changed & BSS_CHANGED_ASSOC)
+               mt7601u_phy_con_cal_onoff(dev, info);
+
+       if (changed & BSS_CHANGED_BSSID) {
+               mt7601u_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
+
+               /* Note: this is a hack because beacon_int is not changed
+                *       on leave nor is any more appropriate event generated.
+                *       rt2x00 doesn't seem to be bothered though.
+                */
+               if (is_zero_ether_addr(info->bssid))
+                       mt7601u_mac_config_tsf(dev, false, 0);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES) {
+               mt7601u_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
+               mt7601u_wr(dev, MT_HT_FBK_CFG0, 0x65432100);
+               mt7601u_wr(dev, MT_HT_FBK_CFG1, 0xedcba980);
+               mt7601u_wr(dev, MT_LG_FBK_CFG0, 0xedcba988);
+               mt7601u_wr(dev, MT_LG_FBK_CFG1, 0x00002100);
+       }
+
+       if (changed & BSS_CHANGED_BEACON_INT)
+               mt7601u_mac_config_tsf(dev, true, info->beacon_int);
+
+       if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+               mt7601u_mac_set_protection(dev, info->use_cts_prot,
+                                          info->ht_operation_mode);
+
+       if (changed & BSS_CHANGED_ERP_PREAMBLE)
+               mt7601u_mac_set_short_preamble(dev, info->use_short_preamble);
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               int slottime = info->use_short_slot ? 9 : 20;
+
+               mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
+                              MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
+       }
+
+       if (changed & BSS_CHANGED_ASSOC)
+               mt7601u_phy_recalibrate_after_assoc(dev);
+
+       mutex_unlock(&dev->mutex);
+}
+
+static int
+mt76_wcid_alloc(struct mt7601u_dev *dev)
+{
+       int i, idx = 0;
+
+       for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
+               idx = ffs(~dev->wcid_mask[i]);
+               if (!idx)
+                       continue;
+
+               idx--;
+               dev->wcid_mask[i] |= BIT(idx);
+               break;
+       }
+
+       idx = i * BITS_PER_LONG + idx;
+       if (idx > 119)
+               return -1;
+
+       return idx;
+}
+
+static int
+mt7601u_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+               struct ieee80211_sta *sta)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
+       struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
+       int ret = 0;
+       int idx = 0;
+
+       mutex_lock(&dev->mutex);
+
+       idx = mt76_wcid_alloc(dev);
+       if (idx < 0) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       msta->wcid.idx = idx;
+       msta->wcid.hw_key_idx = -1;
+       mt7601u_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);
+       mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
+       rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
+       mt7601u_mac_set_ampdu_factor(dev);
+
+out:
+       mutex_unlock(&dev->mutex);
+
+       return ret;
+}
+
+static int
+mt7601u_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
+       int idx = msta->wcid.idx;
+
+       mutex_lock(&dev->mutex);
+       rcu_assign_pointer(dev->wcid[idx], NULL);
+       mt76_set(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
+       dev->wcid_mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG);
+       mt7601u_mac_wcid_setup(dev, idx, 0, NULL);
+       mt7601u_mac_set_ampdu_factor(dev);
+       mutex_unlock(&dev->mutex);
+
+       return 0;
+}
+
+static void
+mt7601u_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
+{
+}
+
+static void
+mt7601u_sw_scan(struct ieee80211_hw *hw,
+               struct ieee80211_vif *vif,
+               const u8 *mac_addr)
+{
+       struct mt7601u_dev *dev = hw->priv;
+
+       mt7601u_agc_save(dev);
+       set_bit(MT7601U_STATE_SCANNING, &dev->state);
+}
+
+static void
+mt7601u_sw_scan_complete(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif)
+{
+       struct mt7601u_dev *dev = hw->priv;
+
+       mt7601u_agc_restore(dev);
+       clear_bit(MT7601U_STATE_SCANNING, &dev->state);
+}
+
+static int
+mt7601u_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+               struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+               struct ieee80211_key_conf *key)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
+       struct mt76_sta *msta = sta ? (struct mt76_sta *) sta->drv_priv : NULL;
+       struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->group_wcid;
+       int idx = key->keyidx;
+       int ret;
+
+       if (cmd == SET_KEY) {
+               key->hw_key_idx = wcid->idx;
+               wcid->hw_key_idx = idx;
+       } else {
+               if (idx == wcid->hw_key_idx)
+                       wcid->hw_key_idx = -1;
+
+               key = NULL;
+       }
+
+       if (!msta) {
+               if (key || wcid->hw_key_idx == idx) {
+                       ret = mt76_mac_wcid_set_key(dev, wcid->idx, key);
+                       if (ret)
+                               return ret;
+               }
+
+               return mt76_mac_shared_key_setup(dev, mvif->idx, idx, key);
+       }
+
+       return mt76_mac_wcid_set_key(dev, msta->wcid.idx, key);
+}
+
+static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+       struct mt7601u_dev *dev = hw->priv;
+
+       mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
+
+       return 0;
+}
+
+static int
+mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                 enum ieee80211_ampdu_mlme_action action,
+                 struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
+
+       WARN_ON(msta->wcid.idx > GROUP_WCID(0));
+
+       switch (action) {
+       case IEEE80211_AMPDU_RX_START:
+               mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
+               break;
+       case IEEE80211_AMPDU_RX_STOP:
+               mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4,
+                          BIT(16 + tid));
+               break;
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]);
+               break;
+       case IEEE80211_AMPDU_TX_STOP_FLUSH:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+               break;
+       case IEEE80211_AMPDU_TX_START:
+               msta->agg_ssn[tid] = *ssn << 4;
+               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               break;
+       case IEEE80211_AMPDU_TX_STOP_CONT:
+               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               break;
+       }
+
+       return 0;
+}
+
+static void
+mt76_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
+       struct ieee80211_sta_rates *rates;
+       struct ieee80211_tx_rate rate = {};
+
+       rcu_read_lock();
+       rates = rcu_dereference(sta->rates);
+
+       if (!rates)
+               goto out;
+
+       rate.idx = rates->rate[0].idx;
+       rate.flags = rates->rate[0].flags;
+       mt76_mac_wcid_set_rate(dev, &msta->wcid, &rate);
+
+out:
+       rcu_read_unlock();
+}
+
+const struct ieee80211_ops mt7601u_ops = {
+       .tx = mt7601u_tx,
+       .start = mt7601u_start,
+       .stop = mt7601u_stop,
+       .add_interface = mt7601u_add_interface,
+       .remove_interface = mt7601u_remove_interface,
+       .config = mt7601u_config,
+       .configure_filter = mt76_configure_filter,
+       .bss_info_changed = mt7601u_bss_info_changed,
+       .sta_add = mt7601u_sta_add,
+       .sta_remove = mt7601u_sta_remove,
+       .sta_notify = mt7601u_sta_notify,
+       .set_key = mt7601u_set_key,
+       .conf_tx = mt7601u_conf_tx,
+       .sw_scan_start = mt7601u_sw_scan,
+       .sw_scan_complete = mt7601u_sw_scan_complete,
+       .ampdu_action = mt76_ampdu_action,
+       .sta_rate_tbl_update = mt76_sta_rate_tbl_update,
+       .set_rts_threshold = mt7601u_set_rts_threshold,
+};
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c
new file mode 100644 (file)
index 0000000..fbb1986
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * (c) Copyright 2002-2010, Ralink Technology, Inc.
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/usb.h>
+#include <linux/skbuff.h>
+
+#include "mt7601u.h"
+#include "dma.h"
+#include "mcu.h"
+#include "usb.h"
+#include "trace.h"
+
+#define MCU_FW_URB_MAX_PAYLOAD         0x3800
+#define MCU_FW_URB_SIZE                        (MCU_FW_URB_MAX_PAYLOAD + 12)
+#define MCU_RESP_URB_SIZE              1024
+
+static inline int firmware_running(struct mt7601u_dev *dev)
+{
+       return mt7601u_rr(dev, MT_MCU_COM_REG0) == 1;
+}
+
+static inline void skb_put_le32(struct sk_buff *skb, u32 val)
+{
+       put_unaligned_le32(val, skb_put(skb, 4));
+}
+
+static inline void mt7601u_dma_skb_wrap_cmd(struct sk_buff *skb,
+                                           u8 seq, enum mcu_cmd cmd)
+{
+       WARN_ON(mt7601u_dma_skb_wrap(skb, CPU_TX_PORT, DMA_COMMAND,
+                                    MT76_SET(MT_TXD_CMD_INFO_SEQ, seq) |
+                                    MT76_SET(MT_TXD_CMD_INFO_TYPE, cmd)));
+}
+
+static inline void trace_mt_mcu_msg_send_cs(struct mt7601u_dev *dev,
+                                           struct sk_buff *skb, bool need_resp)
+{
+       u32 i, csum = 0;
+
+       for (i = 0; i < skb->len / 4; i++)
+               csum ^= get_unaligned_le32(skb->data + i * 4);
+
+       trace_mt_mcu_msg_send(dev, skb, csum, need_resp);
+}
+
+static struct sk_buff *
+mt7601u_mcu_msg_alloc(struct mt7601u_dev *dev, const void *data, int len)
+{
+       struct sk_buff *skb;
+
+       WARN_ON(len % 4); /* if length is not divisible by 4 we need to pad */
+
+       skb = alloc_skb(len + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
+       skb_reserve(skb, MT_DMA_HDR_LEN);
+       memcpy(skb_put(skb, len), data, len);
+
+       return skb;
+}
+
+static int mt7601u_mcu_wait_resp(struct mt7601u_dev *dev, u8 seq)
+{
+       struct urb *urb = dev->mcu.resp.urb;
+       u32 rxfce;
+       int urb_status, ret, i = 5;
+
+       while (i--) {
+               if (!wait_for_completion_timeout(&dev->mcu.resp_cmpl,
+                                                msecs_to_jiffies(300))) {
+                       dev_warn(dev->dev, "Warning: %s retrying\n", __func__);
+                       continue;
+               }
+
+               /* Make copies of important data before reusing the urb */
+               rxfce = get_unaligned_le32(dev->mcu.resp.buf);
+               urb_status = urb->status * mt7601u_urb_has_error(urb);
+
+               ret = mt7601u_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
+                                            &dev->mcu.resp, GFP_KERNEL,
+                                            mt7601u_complete_urb,
+                                            &dev->mcu.resp_cmpl);
+               if (ret)
+                       return ret;
+
+               if (urb_status)
+                       dev_err(dev->dev, "Error: MCU resp urb failed:%d\n",
+                               urb_status);
+
+               if (MT76_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce) == seq &&
+                   MT76_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce) == CMD_DONE)
+                       return 0;
+
+               dev_err(dev->dev, "Error: MCU resp evt:%hhx seq:%hhx-%hhx!\n",
+                       MT76_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce),
+                       seq, MT76_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce));
+       }
+
+       dev_err(dev->dev, "Error: %s timed out\n", __func__);
+       return -ETIMEDOUT;
+}
+
+static int
+mt7601u_mcu_msg_send(struct mt7601u_dev *dev, struct sk_buff *skb,
+                    enum mcu_cmd cmd, bool wait_resp)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+       unsigned cmd_pipe = usb_sndbulkpipe(usb_dev,
+                                           dev->out_eps[MT_EP_OUT_INBAND_CMD]);
+       int sent, ret;
+       u8 seq = 0;
+
+       if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return 0;
+
+       mutex_lock(&dev->mcu.mutex);
+
+       if (wait_resp)
+               while (!seq)
+                       seq = ++dev->mcu.msg_seq & 0xf;
+
+       mt7601u_dma_skb_wrap_cmd(skb, seq, cmd);
+
+       if (dev->mcu.resp_cmpl.done)
+               dev_err(dev->dev, "Error: MCU response pre-completed!\n");
+
+       trace_mt_mcu_msg_send_cs(dev, skb, wait_resp);
+       trace_mt_submit_urb_sync(dev, cmd_pipe, skb->len);
+       ret = usb_bulk_msg(usb_dev, cmd_pipe, skb->data, skb->len, &sent, 500);
+       if (ret) {
+               dev_err(dev->dev, "Error: send MCU cmd failed:%d\n", ret);
+               goto out;
+       }
+       if (sent != skb->len)
+               dev_err(dev->dev, "Error: %s sent != skb->len\n", __func__);
+
+       if (wait_resp)
+               ret = mt7601u_mcu_wait_resp(dev, seq);
+out:
+       mutex_unlock(&dev->mcu.mutex);
+
+       consume_skb(skb);
+
+       return ret;
+}
+
+static int mt7601u_mcu_function_select(struct mt7601u_dev *dev,
+                                      enum mcu_function func, u32 val)
+{
+       struct sk_buff *skb;
+       struct {
+               __le32 id;
+               __le32 value;
+       } __packed __aligned(4) msg = {
+               .id = cpu_to_le32(func),
+               .value = cpu_to_le32(val),
+       };
+
+       skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+       return mt7601u_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5);
+}
+
+int mt7601u_mcu_tssi_read_kick(struct mt7601u_dev *dev, int use_hvga)
+{
+       int ret;
+
+       if (!test_bit(MT7601U_STATE_MCU_RUNNING, &dev->state))
+               return 0;
+
+       ret = mt7601u_mcu_function_select(dev, ATOMIC_TSSI_SETTING,
+                                         use_hvga);
+       if (ret) {
+               dev_warn(dev->dev, "Warning: MCU TSSI read kick failed\n");
+               return ret;
+       }
+
+       dev->tssi_read_trig = true;
+
+       return 0;
+}
+
+int
+mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val)
+{
+       struct sk_buff *skb;
+       struct {
+               __le32 id;
+               __le32 value;
+       } __packed __aligned(4) msg = {
+               .id = cpu_to_le32(cal),
+               .value = cpu_to_le32(val),
+       };
+
+       skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+       return mt7601u_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true);
+}
+
+int mt7601u_write_reg_pairs(struct mt7601u_dev *dev, u32 base,
+                           const struct mt76_reg_pair *data, int n)
+{
+       const int max_vals_per_cmd = INBAND_PACKET_MAX_LEN / 8;
+       struct sk_buff *skb;
+       int cnt, i, ret;
+
+       if (!n)
+               return 0;
+
+       cnt = min(max_vals_per_cmd, n);
+
+       skb = alloc_skb(cnt * 8 + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+       skb_reserve(skb, MT_DMA_HDR_LEN);
+
+       for (i = 0; i < cnt; i++) {
+               skb_put_le32(skb, base + data[i].reg);
+               skb_put_le32(skb, data[i].value);
+       }
+
+       ret = mt7601u_mcu_msg_send(dev, skb, CMD_RANDOM_WRITE, cnt == n);
+       if (ret)
+               return ret;
+
+       return mt7601u_write_reg_pairs(dev, base, data + cnt, n - cnt);
+}
+
+int mt7601u_burst_write_regs(struct mt7601u_dev *dev, u32 offset,
+                            const u32 *data, int n)
+{
+       const int max_regs_per_cmd = INBAND_PACKET_MAX_LEN / 4 - 1;
+       struct sk_buff *skb;
+       int cnt, i, ret;
+
+       if (!n)
+               return 0;
+
+       cnt = min(max_regs_per_cmd, n);
+
+       skb = alloc_skb(cnt * 4 + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+       skb_reserve(skb, MT_DMA_HDR_LEN);
+
+       skb_put_le32(skb, MT_MCU_MEMMAP_WLAN + offset);
+       for (i = 0; i < cnt; i++)
+               skb_put_le32(skb, data[i]);
+
+       ret = mt7601u_mcu_msg_send(dev, skb, CMD_BURST_WRITE, cnt == n);
+       if (ret)
+               return ret;
+
+       return mt7601u_burst_write_regs(dev, offset + cnt * 4,
+                                       data + cnt, n - cnt);
+}
+
+struct mt76_fw_header {
+       __le32 ilm_len;
+       __le32 dlm_len;
+       __le16 build_ver;
+       __le16 fw_ver;
+       u8 pad[4];
+       char build_time[16];
+};
+
+struct mt76_fw {
+       struct mt76_fw_header hdr;
+       u8 ivb[MT_MCU_IVB_SIZE];
+       u8 ilm[];
+};
+
+static int __mt7601u_dma_fw(struct mt7601u_dev *dev,
+                           const struct mt7601u_dma_buf *dma_buf,
+                           const void *data, u32 len, u32 dst_addr)
+{
+       DECLARE_COMPLETION_ONSTACK(cmpl);
+       struct mt7601u_dma_buf buf = *dma_buf; /* we need to fake length */
+       __le32 reg;
+       u32 val;
+       int ret;
+
+       reg = cpu_to_le32(MT76_SET(MT_TXD_INFO_TYPE, DMA_PACKET) |
+                         MT76_SET(MT_TXD_INFO_D_PORT, CPU_TX_PORT) |
+                         MT76_SET(MT_TXD_INFO_LEN, len));
+       memcpy(buf.buf, &reg, sizeof(reg));
+       memcpy(buf.buf + sizeof(reg), data, len);
+       memset(buf.buf + sizeof(reg) + len, 0, 8);
+
+       ret = mt7601u_vendor_single_wr(dev, MT_VEND_WRITE_FCE,
+                                      MT_FCE_DMA_ADDR, dst_addr);
+       if (ret)
+               return ret;
+       len = roundup(len, 4);
+       ret = mt7601u_vendor_single_wr(dev, MT_VEND_WRITE_FCE,
+                                      MT_FCE_DMA_LEN, len << 16);
+       if (ret)
+               return ret;
+
+       buf.len = MT_DMA_HDR_LEN + len + 4;
+       ret = mt7601u_usb_submit_buf(dev, USB_DIR_OUT, MT_EP_OUT_INBAND_CMD,
+                                    &buf, GFP_KERNEL,
+                                    mt7601u_complete_urb, &cmpl);
+       if (ret)
+               return ret;
+
+       if (!wait_for_completion_timeout(&cmpl, msecs_to_jiffies(1000))) {
+               dev_err(dev->dev, "Error: firmware upload timed out\n");
+               usb_kill_urb(buf.urb);
+               return -ETIMEDOUT;
+       }
+       if (mt7601u_urb_has_error(buf.urb)) {
+               dev_err(dev->dev, "Error: firmware upload urb failed:%d\n",
+                       buf.urb->status);
+               return buf.urb->status;
+       }
+
+       val = mt7601u_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX);
+       val++;
+       mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX, val);
+
+       return 0;
+}
+
+static int
+mt7601u_dma_fw(struct mt7601u_dev *dev, struct mt7601u_dma_buf *dma_buf,
+              const void *data, int len, u32 dst_addr)
+{
+       int n, ret;
+
+       if (len == 0)
+               return 0;
+
+       n = min(MCU_FW_URB_MAX_PAYLOAD, len);
+       ret = __mt7601u_dma_fw(dev, dma_buf, data, n, dst_addr);
+       if (ret)
+               return ret;
+
+       if (!mt76_poll_msec(dev, MT_MCU_COM_REG1, BIT(31), BIT(31), 500))
+               return -ETIMEDOUT;
+
+       return mt7601u_dma_fw(dev, dma_buf, data + n, len - n, dst_addr + n);
+}
+
+static int
+mt7601u_upload_firmware(struct mt7601u_dev *dev, const struct mt76_fw *fw)
+{
+       struct mt7601u_dma_buf dma_buf;
+       void *ivb;
+       u32 ilm_len, dlm_len;
+       int i, ret;
+
+       ivb = kmemdup(fw->ivb, sizeof(fw->ivb), GFP_KERNEL);
+       if (!ivb || mt7601u_usb_alloc_buf(dev, MCU_FW_URB_SIZE, &dma_buf)) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       ilm_len = le32_to_cpu(fw->hdr.ilm_len) - sizeof(fw->ivb);
+       dev_dbg(dev->dev, "loading FW - ILM %u + IVB %zu\n",
+               ilm_len, sizeof(fw->ivb));
+       ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm, ilm_len, sizeof(fw->ivb));
+       if (ret)
+               goto error;
+
+       dlm_len = le32_to_cpu(fw->hdr.dlm_len);
+       dev_dbg(dev->dev, "loading FW - DLM %u\n", dlm_len);
+       ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm + ilm_len,
+                            dlm_len, MT_MCU_DLM_OFFSET);
+       if (ret)
+               goto error;
+
+       ret = mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
+                                    0x12, 0, ivb, sizeof(fw->ivb));
+       if (ret < 0)
+               goto error;
+       ret = 0;
+
+       for (i = 100; i && !firmware_running(dev); i--)
+               msleep(10);
+       if (!i) {
+               ret = -ETIMEDOUT;
+               goto error;
+       }
+
+       dev_dbg(dev->dev, "Firmware running!\n");
+error:
+       kfree(ivb);
+       mt7601u_usb_free_buf(dev, &dma_buf);
+
+       return ret;
+}
+
+static int mt7601u_load_firmware(struct mt7601u_dev *dev)
+{
+       const struct firmware *fw;
+       const struct mt76_fw_header *hdr;
+       int len, ret;
+       u32 val;
+
+       mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
+                                        MT_USB_DMA_CFG_TX_BULK_EN));
+
+       if (firmware_running(dev))
+               return 0;
+
+       ret = request_firmware(&fw, MT7601U_FIRMWARE, dev->dev);
+       if (ret)
+               return ret;
+
+       if (!fw || !fw->data || fw->size < sizeof(*hdr))
+               goto err_inv_fw;
+
+       hdr = (const struct mt76_fw_header *) fw->data;
+
+       if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
+               goto err_inv_fw;
+
+       len = sizeof(*hdr);
+       len += le32_to_cpu(hdr->ilm_len);
+       len += le32_to_cpu(hdr->dlm_len);
+
+       if (fw->size != len)
+               goto err_inv_fw;
+
+       val = le16_to_cpu(hdr->fw_ver);
+       dev_info(dev->dev,
+                "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
+                (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
+                le16_to_cpu(hdr->build_ver), hdr->build_time);
+
+       len = le32_to_cpu(hdr->ilm_len);
+
+       mt7601u_wr(dev, 0x94c, 0);
+       mt7601u_wr(dev, MT_FCE_PSE_CTRL, 0);
+
+       mt7601u_vendor_reset(dev);
+       msleep(5);
+
+       mt7601u_wr(dev, 0xa44, 0);
+       mt7601u_wr(dev, 0x230, 0x84210);
+       mt7601u_wr(dev, 0x400, 0x80c00);
+       mt7601u_wr(dev, 0x800, 1);
+
+       mt7601u_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
+                                        MT_PBF_CFG_TX1Q_EN |
+                                        MT_PBF_CFG_TX2Q_EN |
+                                        MT_PBF_CFG_TX3Q_EN));
+
+       mt7601u_wr(dev, MT_FCE_PSE_CTRL, 1);
+
+       mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
+                                        MT_USB_DMA_CFG_TX_BULK_EN));
+       val = mt76_set(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_CLR);
+       val &= ~MT_USB_DMA_CFG_TX_CLR;
+       mt7601u_wr(dev, MT_USB_DMA_CFG, val);
+
+       /* FCE tx_fs_base_ptr */
+       mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
+       /* FCE tx_fs_max_cnt */
+       mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
+       /* FCE pdma enable */
+       mt7601u_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
+       /* FCE skip_fs_en */
+       mt7601u_wr(dev, MT_FCE_SKIP_FS, 3);
+
+       ret = mt7601u_upload_firmware(dev, (const struct mt76_fw *)fw->data);
+
+       release_firmware(fw);
+
+       return ret;
+
+err_inv_fw:
+       dev_err(dev->dev, "Invalid firmware image\n");
+       release_firmware(fw);
+       return -ENOENT;
+}
+
+int mt7601u_mcu_init(struct mt7601u_dev *dev)
+{
+       int ret;
+
+       mutex_init(&dev->mcu.mutex);
+
+       ret = mt7601u_load_firmware(dev);
+       if (ret)
+               return ret;
+
+       set_bit(MT7601U_STATE_MCU_RUNNING, &dev->state);
+
+       return 0;
+}
+
+int mt7601u_mcu_cmd_init(struct mt7601u_dev *dev)
+{
+       int ret;
+
+       ret = mt7601u_mcu_function_select(dev, Q_SELECT, 1);
+       if (ret)
+               return ret;
+
+       init_completion(&dev->mcu.resp_cmpl);
+       if (mt7601u_usb_alloc_buf(dev, MCU_RESP_URB_SIZE, &dev->mcu.resp)) {
+               mt7601u_usb_free_buf(dev, &dev->mcu.resp);
+               return -ENOMEM;
+       }
+
+       ret = mt7601u_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
+                                    &dev->mcu.resp, GFP_KERNEL,
+                                    mt7601u_complete_urb, &dev->mcu.resp_cmpl);
+       if (ret) {
+               mt7601u_usb_free_buf(dev, &dev->mcu.resp);
+               return ret;
+       }
+
+       return 0;
+}
+
+void mt7601u_mcu_cmd_deinit(struct mt7601u_dev *dev)
+{
+       usb_kill_urb(dev->mcu.resp.urb);
+       mt7601u_usb_free_buf(dev, &dev->mcu.resp);
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.h b/drivers/net/wireless/mediatek/mt7601u/mcu.h
new file mode 100644 (file)
index 0000000..4a66d10
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_MCU_H
+#define __MT7601U_MCU_H
+
+struct mt7601u_dev;
+
+/* Register definitions */
+#define MT_MCU_RESET_CTL               0x070C
+#define MT_MCU_INT_LEVEL               0x0718
+#define MT_MCU_COM_REG0                        0x0730
+#define MT_MCU_COM_REG1                        0x0734
+#define MT_MCU_COM_REG2                        0x0738
+#define MT_MCU_COM_REG3                        0x073C
+
+#define MT_MCU_IVB_SIZE                        0x40
+#define MT_MCU_DLM_OFFSET              0x80000
+
+#define MT_MCU_MEMMAP_WLAN             0x00410000
+#define MT_MCU_MEMMAP_BBP              0x40000000
+#define MT_MCU_MEMMAP_RF               0x80000000
+
+#define INBAND_PACKET_MAX_LEN          192
+
+enum mcu_cmd {
+       CMD_FUN_SET_OP = 1,
+       CMD_LOAD_CR = 2,
+       CMD_INIT_GAIN_OP = 3,
+       CMD_DYNC_VGA_OP = 6,
+       CMD_TDLS_CH_SW = 7,
+       CMD_BURST_WRITE = 8,
+       CMD_READ_MODIFY_WRITE = 9,
+       CMD_RANDOM_READ = 10,
+       CMD_BURST_READ = 11,
+       CMD_RANDOM_WRITE = 12,
+       CMD_LED_MODE_OP = 16,
+       CMD_POWER_SAVING_OP = 20,
+       CMD_WOW_CONFIG = 21,
+       CMD_WOW_QUERY = 22,
+       CMD_WOW_FEATURE = 24,
+       CMD_CARRIER_DETECT_OP = 28,
+       CMD_RADOR_DETECT_OP = 29,
+       CMD_SWITCH_CHANNEL_OP = 30,
+       CMD_CALIBRATION_OP = 31,
+       CMD_BEACON_OP = 32,
+       CMD_ANTENNA_OP = 33,
+};
+
+enum mcu_function {
+       Q_SELECT = 1,
+       ATOMIC_TSSI_SETTING = 5,
+};
+
+enum mcu_power_mode {
+       RADIO_OFF = 0x30,
+       RADIO_ON = 0x31,
+       RADIO_OFF_AUTO_WAKEUP = 0x32,
+       RADIO_OFF_ADVANCE = 0x33,
+       RADIO_ON_ADVANCE = 0x34,
+};
+
+enum mcu_calibrate {
+       MCU_CAL_R = 1,
+       MCU_CAL_DCOC,
+       MCU_CAL_LC,
+       MCU_CAL_LOFT,
+       MCU_CAL_TXIQ,
+       MCU_CAL_BW,
+       MCU_CAL_DPD,
+       MCU_CAL_RXIQ,
+       MCU_CAL_TXDCOC,
+};
+
+int mt7601u_mcu_init(struct mt7601u_dev *dev);
+int mt7601u_mcu_cmd_init(struct mt7601u_dev *dev);
+void mt7601u_mcu_cmd_deinit(struct mt7601u_dev *dev);
+
+int
+mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val);
+int mt7601u_mcu_tssi_read_kick(struct mt7601u_dev *dev, int use_hvga);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
new file mode 100644 (file)
index 0000000..9102be6
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef MT7601U_H
+#define MT7601U_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/completion.h>
+#include <net/mac80211.h>
+#include <linux/debugfs.h>
+
+#include "regs.h"
+#include "util.h"
+
+#define MT_CALIBRATE_INTERVAL          (4 * HZ)
+
+#define MT_FREQ_CAL_INIT_DELAY         (30 * HZ)
+#define MT_FREQ_CAL_CHECK_INTERVAL     (10 * HZ)
+#define MT_FREQ_CAL_ADJ_INTERVAL       (HZ / 2)
+
+#define MT_BBP_REG_VERSION             0x00
+
+#define MT_USB_AGGR_SIZE_LIMIT         28 /* * 1024B */
+#define MT_USB_AGGR_TIMEOUT            0x80 /* * 33ns */
+#define MT_RX_ORDER                    3
+#define MT_RX_URB_SIZE                 (PAGE_SIZE << MT_RX_ORDER)
+
+struct mt7601u_dma_buf {
+       struct urb *urb;
+       void *buf;
+       dma_addr_t dma;
+       size_t len;
+};
+
+struct mt7601u_mcu {
+       struct mutex mutex;
+
+       u8 msg_seq;
+
+       struct mt7601u_dma_buf resp;
+       struct completion resp_cmpl;
+};
+
+struct mt7601u_freq_cal {
+       struct delayed_work work;
+       u8 freq;
+       bool enabled;
+       bool adjusting;
+};
+
+struct mac_stats {
+       u64 rx_stat[6];
+       u64 tx_stat[6];
+       u64 aggr_stat[2];
+       u64 aggr_n[32];
+       u64 zero_len_del[2];
+};
+
+#define N_RX_ENTRIES   16
+struct mt7601u_rx_queue {
+       struct mt7601u_dev *dev;
+
+       struct mt7601u_dma_buf_rx {
+               struct urb *urb;
+               struct page *p;
+       } e[N_RX_ENTRIES];
+
+       unsigned int start;
+       unsigned int end;
+       unsigned int entries;
+       unsigned int pending;
+};
+
+#define N_TX_ENTRIES   64
+
+struct mt7601u_tx_queue {
+       struct mt7601u_dev *dev;
+
+       struct mt7601u_dma_buf_tx {
+               struct urb *urb;
+               struct sk_buff *skb;
+       } e[N_TX_ENTRIES];
+
+       unsigned int start;
+       unsigned int end;
+       unsigned int entries;
+       unsigned int used;
+       unsigned int fifo_seq;
+};
+
+/* WCID allocation:
+ *     0: mcast wcid
+ *     1: bssid wcid
+ *  1...: STAs
+ * ...7e: group wcids
+ *    7f: reserved
+ */
+#define N_WCIDS                128
+#define GROUP_WCID(idx)        (N_WCIDS - 2 - idx)
+
+struct mt7601u_eeprom_params;
+
+#define MT_EE_TEMPERATURE_SLOPE                39
+#define MT_FREQ_OFFSET_INVALID         -128
+
+enum mt_temp_mode {
+       MT_TEMP_MODE_NORMAL,
+       MT_TEMP_MODE_HIGH,
+       MT_TEMP_MODE_LOW,
+};
+
+enum mt_bw {
+       MT_BW_20,
+       MT_BW_40,
+};
+
+enum {
+       MT7601U_STATE_INITIALIZED,
+       MT7601U_STATE_REMOVED,
+       MT7601U_STATE_WLAN_RUNNING,
+       MT7601U_STATE_MCU_RUNNING,
+       MT7601U_STATE_SCANNING,
+       MT7601U_STATE_READING_STATS,
+       MT7601U_STATE_MORE_STATS,
+};
+
+/**
+ * struct mt7601u_dev - adapter structure
+ * @lock:              protects @wcid->tx_rate.
+ * @tx_lock:           protects @tx_q and changes of MT7601U_STATE_*_STATS
+                       flags in @state.
+ * @rx_lock:           protects @rx_q.
+ * @con_mon_lock:      protects @ap_bssid, @bcn_*, @avg_rssi.
+ * @mutex:             ensures exclusive access from mac80211 callbacks.
+ * @vendor_req_mutex:  ensures atomicity of vendor requests.
+ * @reg_atomic_mutex:  ensures atomicity of indirect register accesses
+ *                     (accesses to RF and BBP).
+ * @hw_atomic_mutex:   ensures exclusive access to HW during critical
+ *                     operations (power management, channel switch).
+ */
+struct mt7601u_dev {
+       struct ieee80211_hw *hw;
+       struct device *dev;
+
+       unsigned long state;
+
+       struct mutex mutex;
+
+       unsigned long wcid_mask[N_WCIDS / BITS_PER_LONG];
+
+       struct cfg80211_chan_def chandef;
+       struct ieee80211_supported_band *sband_2g;
+
+       struct mt7601u_mcu mcu;
+
+       struct delayed_work cal_work;
+       struct delayed_work mac_work;
+
+       struct workqueue_struct *stat_wq;
+       struct delayed_work stat_work;
+
+       struct mt76_wcid *mon_wcid;
+       struct mt76_wcid __rcu *wcid[N_WCIDS];
+
+       spinlock_t lock;
+
+       const u16 *beacon_offsets;
+
+       u8 macaddr[ETH_ALEN];
+       struct mt7601u_eeprom_params *ee;
+
+       struct mutex vendor_req_mutex;
+       struct mutex reg_atomic_mutex;
+       struct mutex hw_atomic_mutex;
+
+       u32 rxfilter;
+       u32 debugfs_reg;
+
+       u8 out_eps[8];
+       u8 in_eps[8];
+       u16 out_max_packet;
+       u16 in_max_packet;
+
+       /* TX */
+       spinlock_t tx_lock;
+       struct mt7601u_tx_queue *tx_q;
+
+       atomic_t avg_ampdu_len;
+
+       /* RX */
+       spinlock_t rx_lock;
+       struct tasklet_struct rx_tasklet;
+       struct mt7601u_rx_queue rx_q;
+
+       /* Connection monitoring things */
+       spinlock_t con_mon_lock;
+       u8 ap_bssid[ETH_ALEN];
+
+       s8 bcn_freq_off;
+       u8 bcn_phy_mode;
+
+       int avg_rssi; /* starts at 0 and converges */
+
+       u8 agc_save;
+
+       struct mt7601u_freq_cal freq_cal;
+
+       bool tssi_read_trig;
+
+       s8 tssi_init;
+       s8 tssi_init_hvga;
+       s16 tssi_init_hvga_offset_db;
+
+       int prev_pwr_diff;
+
+       enum mt_temp_mode temp_mode;
+       int curr_temp;
+       int dpd_temp;
+       s8 raw_temp;
+       bool pll_lock_protect;
+
+       u8 bw;
+       bool chan_ext_below;
+
+       /* PA mode */
+       u32 rf_pa_mode[2];
+
+       struct mac_stats stats;
+};
+
+struct mt7601u_tssi_params {
+       char tssi0;
+       int trgt_power;
+};
+
+struct mt76_wcid {
+       u8 idx;
+       u8 hw_key_idx;
+
+       u16 tx_rate;
+       bool tx_rate_set;
+       u8 tx_rate_nss;
+};
+
+struct mt76_vif {
+       u8 idx;
+
+       struct mt76_wcid group_wcid;
+};
+
+struct mt76_sta {
+       struct mt76_wcid wcid;
+       u16 agg_ssn[IEEE80211_NUM_TIDS];
+};
+
+struct mt76_reg_pair {
+       u32 reg;
+       u32 value;
+};
+
+struct mt7601u_rxwi;
+
+extern const struct ieee80211_ops mt7601u_ops;
+
+void mt7601u_init_debugfs(struct mt7601u_dev *dev);
+
+u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset);
+void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val);
+u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val);
+u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val);
+void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
+                    const void *data, int len);
+
+int mt7601u_wait_asic_ready(struct mt7601u_dev *dev);
+bool mt76_poll(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
+              int timeout);
+bool mt76_poll_msec(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
+                   int timeout);
+
+/* Compatibility with mt76 */
+#define mt76_rmw_field(_dev, _reg, _field, _val)       \
+       mt76_rmw(_dev, _reg, _field, MT76_SET(_field, _val))
+
+static inline u32 mt76_rr(struct mt7601u_dev *dev, u32 offset)
+{
+       return mt7601u_rr(dev, offset);
+}
+
+static inline void mt76_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
+{
+       return mt7601u_wr(dev, offset, val);
+}
+
+static inline u32
+mt76_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
+{
+       return mt7601u_rmw(dev, offset, mask, val);
+}
+
+static inline u32 mt76_set(struct mt7601u_dev *dev, u32 offset, u32 val)
+{
+       return mt76_rmw(dev, offset, 0, val);
+}
+
+static inline u32 mt76_clear(struct mt7601u_dev *dev, u32 offset, u32 val)
+{
+       return mt76_rmw(dev, offset, val, 0);
+}
+
+int mt7601u_write_reg_pairs(struct mt7601u_dev *dev, u32 base,
+                           const struct mt76_reg_pair *data, int len);
+int mt7601u_burst_write_regs(struct mt7601u_dev *dev, u32 offset,
+                            const u32 *data, int n);
+void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr);
+
+/* Init */
+struct mt7601u_dev *mt7601u_alloc_device(struct device *dev);
+int mt7601u_init_hardware(struct mt7601u_dev *dev);
+int mt7601u_register_device(struct mt7601u_dev *dev);
+void mt7601u_cleanup(struct mt7601u_dev *dev);
+
+int mt7601u_mac_start(struct mt7601u_dev *dev);
+void mt7601u_mac_stop(struct mt7601u_dev *dev);
+
+/* PHY */
+int mt7601u_phy_init(struct mt7601u_dev *dev);
+int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev);
+void mt7601u_set_rx_path(struct mt7601u_dev *dev, u8 path);
+void mt7601u_set_tx_dac(struct mt7601u_dev *dev, u8 path);
+int mt7601u_bbp_set_bw(struct mt7601u_dev *dev, int bw);
+void mt7601u_agc_save(struct mt7601u_dev *dev);
+void mt7601u_agc_restore(struct mt7601u_dev *dev);
+int mt7601u_phy_set_channel(struct mt7601u_dev *dev,
+                           struct cfg80211_chan_def *chandef);
+void mt7601u_phy_recalibrate_after_assoc(struct mt7601u_dev *dev);
+int mt7601u_phy_get_rssi(struct mt7601u_dev *dev,
+                        struct mt7601u_rxwi *rxwi, u16 rate);
+void mt7601u_phy_con_cal_onoff(struct mt7601u_dev *dev,
+                              struct ieee80211_bss_conf *info);
+
+/* MAC */
+void mt7601u_mac_work(struct work_struct *work);
+void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
+                               int ht_mode);
+void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb);
+void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval);
+void
+mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
+void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev);
+
+/* TX */
+void mt7601u_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+               struct sk_buff *skb);
+int mt7601u_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                   u16 queue, const struct ieee80211_tx_queue_params *params);
+void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb);
+void mt7601u_tx_stat(struct work_struct *work);
+
+/* util */
+void mt76_remove_hdr_pad(struct sk_buff *skb);
+int mt76_insert_hdr_pad(struct sk_buff *skb);
+
+u32 mt7601u_bbp_set_ctrlch(struct mt7601u_dev *dev, bool below);
+
+static inline u32 mt7601u_mac_set_ctrlch(struct mt7601u_dev *dev, bool below)
+{
+       return mt7601u_rmc(dev, MT_TX_BAND_CFG, 1, below);
+}
+
+int mt7601u_dma_init(struct mt7601u_dev *dev);
+void mt7601u_dma_cleanup(struct mt7601u_dev *dev);
+
+int mt7601u_dma_enqueue_tx(struct mt7601u_dev *dev, struct sk_buff *skb,
+                          struct mt76_wcid *wcid, int hw_q);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/phy.c b/drivers/net/wireless/mediatek/mt7601u/phy.c
new file mode 100644 (file)
index 0000000..1908af6
--- /dev/null
@@ -0,0 +1,1251 @@
+/*
+ * (c) Copyright 2002-2010, Ralink Technology, Inc.
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "mcu.h"
+#include "eeprom.h"
+#include "trace.h"
+#include "initvals_phy.h"
+
+#include <linux/etherdevice.h>
+
+static void mt7601u_agc_reset(struct mt7601u_dev *dev);
+
+static int
+mt7601u_rf_wr(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 value)
+{
+       int ret = 0;
+
+       if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
+           WARN_ON(offset > 63))
+               return -EINVAL;
+       if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return 0;
+
+       mutex_lock(&dev->reg_atomic_mutex);
+
+       if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) {
+               ret = -ETIMEDOUT;
+               goto out;
+       }
+
+       mt7601u_wr(dev, MT_RF_CSR_CFG, MT76_SET(MT_RF_CSR_CFG_DATA, value) |
+                                      MT76_SET(MT_RF_CSR_CFG_REG_BANK, bank) |
+                                      MT76_SET(MT_RF_CSR_CFG_REG_ID, offset) |
+                                      MT_RF_CSR_CFG_WR |
+                                      MT_RF_CSR_CFG_KICK);
+       trace_rf_write(dev, bank, offset, value);
+out:
+       mutex_unlock(&dev->reg_atomic_mutex);
+
+       if (ret < 0)
+               dev_err(dev->dev, "Error: RF write %02hhx:%02hhx failed:%d!!\n",
+                       bank, offset, ret);
+
+       return ret;
+}
+
+static int
+mt7601u_rf_rr(struct mt7601u_dev *dev, u8 bank, u8 offset)
+{
+       int ret = -ETIMEDOUT;
+       u32 val;
+
+       if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
+           WARN_ON(offset > 63))
+               return -EINVAL;
+       if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return 0xff;
+
+       mutex_lock(&dev->reg_atomic_mutex);
+
+       if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
+               goto out;
+
+       mt7601u_wr(dev, MT_RF_CSR_CFG, MT76_SET(MT_RF_CSR_CFG_REG_BANK, bank) |
+                                      MT76_SET(MT_RF_CSR_CFG_REG_ID, offset) |
+                                      MT_RF_CSR_CFG_KICK);
+
+       if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
+               goto out;
+
+       val = mt7601u_rr(dev, MT_RF_CSR_CFG);
+       if (MT76_GET(MT_RF_CSR_CFG_REG_ID, val) == offset &&
+           MT76_GET(MT_RF_CSR_CFG_REG_BANK, val) == bank) {
+               ret = MT76_GET(MT_RF_CSR_CFG_DATA, val);
+               trace_rf_read(dev, bank, offset, ret);
+       }
+out:
+       mutex_unlock(&dev->reg_atomic_mutex);
+
+       if (ret < 0)
+               dev_err(dev->dev, "Error: RF read %02hhx:%02hhx failed:%d!!\n",
+                       bank, offset, ret);
+
+       return ret;
+}
+
+static int
+mt7601u_rf_rmw(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 mask, u8 val)
+{
+       int ret;
+
+       ret = mt7601u_rf_rr(dev, bank, offset);
+       if (ret < 0)
+               return ret;
+       val |= ret & ~mask;
+       ret = mt7601u_rf_wr(dev, bank, offset, val);
+       if (ret)
+               return ret;
+
+       return val;
+}
+
+static int
+mt7601u_rf_set(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 val)
+{
+       return mt7601u_rf_rmw(dev, bank, offset, 0, val);
+}
+
+static int
+mt7601u_rf_clear(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 mask)
+{
+       return mt7601u_rf_rmw(dev, bank, offset, mask, 0);
+}
+
+static void mt7601u_bbp_wr(struct mt7601u_dev *dev, u8 offset, u8 val)
+{
+       if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
+           test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return;
+
+       mutex_lock(&dev->reg_atomic_mutex);
+
+       if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000)) {
+               dev_err(dev->dev, "Error: BBP write %02hhx failed!!\n", offset);
+               goto out;
+       }
+
+       mt7601u_wr(dev, MT_BBP_CSR_CFG,
+                  MT76_SET(MT_BBP_CSR_CFG_VAL, val) |
+                  MT76_SET(MT_BBP_CSR_CFG_REG_NUM, offset) |
+                  MT_BBP_CSR_CFG_RW_MODE | MT_BBP_CSR_CFG_BUSY);
+       trace_bbp_write(dev, offset, val);
+out:
+       mutex_unlock(&dev->reg_atomic_mutex);
+}
+
+static int mt7601u_bbp_rr(struct mt7601u_dev *dev, u8 offset)
+{
+       u32 val;
+       int ret = -ETIMEDOUT;
+
+       if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)))
+               return -EINVAL;
+       if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
+               return 0xff;
+
+       mutex_lock(&dev->reg_atomic_mutex);
+
+       if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000))
+               goto out;
+
+       mt7601u_wr(dev, MT_BBP_CSR_CFG,
+                  MT76_SET(MT_BBP_CSR_CFG_REG_NUM, offset) |
+                  MT_BBP_CSR_CFG_RW_MODE | MT_BBP_CSR_CFG_BUSY |
+                  MT_BBP_CSR_CFG_READ);
+
+       if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000))
+               goto out;
+
+       val = mt7601u_rr(dev, MT_BBP_CSR_CFG);
+       if (MT76_GET(MT_BBP_CSR_CFG_REG_NUM, val) == offset) {
+               ret = MT76_GET(MT_BBP_CSR_CFG_VAL, val);
+               trace_bbp_read(dev, offset, ret);
+       }
+out:
+       mutex_unlock(&dev->reg_atomic_mutex);
+
+       if (ret < 0)
+               dev_err(dev->dev, "Error: BBP read %02hhx failed:%d!!\n",
+                       offset, ret);
+
+       return ret;
+}
+
+static int mt7601u_bbp_rmw(struct mt7601u_dev *dev, u8 offset, u8 mask, u8 val)
+{
+       int ret;
+
+       ret = mt7601u_bbp_rr(dev, offset);
+       if (ret < 0)
+               return ret;
+       val |= ret & ~mask;
+       mt7601u_bbp_wr(dev, offset, val);
+
+       return val;
+}
+
+static u8 mt7601u_bbp_rmc(struct mt7601u_dev *dev, u8 offset, u8 mask, u8 val)
+{
+       int ret;
+
+       ret = mt7601u_bbp_rr(dev, offset);
+       if (ret < 0)
+               return ret;
+       val |= ret & ~mask;
+       if (ret != val)
+               mt7601u_bbp_wr(dev, offset, val);
+
+       return val;
+}
+
+int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev)
+{
+       int i = 20;
+       u8 val;
+
+       do {
+               val = mt7601u_bbp_rr(dev, MT_BBP_REG_VERSION);
+               if (val && ~val)
+                       break;
+       } while (--i);
+
+       if (!i) {
+               dev_err(dev->dev, "Error: BBP is not ready\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+u32 mt7601u_bbp_set_ctrlch(struct mt7601u_dev *dev, bool below)
+{
+       return mt7601u_bbp_rmc(dev, 3, 0x20, below ? 0x20 : 0);
+}
+
+int mt7601u_phy_get_rssi(struct mt7601u_dev *dev,
+                        struct mt7601u_rxwi *rxwi, u16 rate)
+{
+       static const s8 lna[2][2][3] = {
+               /* main LNA */ {
+                       /* bw20 */ { -2, 15, 33 },
+                       /* bw40 */ {  0, 16, 34 }
+               },
+               /*  aux LNA */ {
+                       /* bw20 */ { -2, 15, 33 },
+                       /* bw40 */ { -2, 16, 34 }
+               }
+       };
+       int bw = MT76_GET(MT_RXWI_RATE_BW, rate);
+       int aux_lna = MT76_GET(MT_RXWI_ANT_AUX_LNA, rxwi->ant);
+       int lna_id = MT76_GET(MT_RXWI_GAIN_RSSI_LNA_ID, rxwi->gain);
+       int val;
+
+       if (lna_id) /* LNA id can be 0, 2, 3. */
+               lna_id--;
+
+       val = 8;
+       val -= lna[aux_lna][bw][lna_id];
+       val -= MT76_GET(MT_RXWI_GAIN_RSSI_VAL, rxwi->gain);
+       val -= dev->ee->lna_gain;
+       val -= dev->ee->rssi_offset[0];
+
+       return val;
+}
+
+static void mt7601u_vco_cal(struct mt7601u_dev *dev)
+{
+       mt7601u_rf_wr(dev, 0, 4, 0x0a);
+       mt7601u_rf_wr(dev, 0, 5, 0x20);
+       mt7601u_rf_set(dev, 0, 4, BIT(7));
+       msleep(2);
+}
+
+static int mt7601u_set_bw_filter(struct mt7601u_dev *dev, bool cal)
+{
+       u32 filter = 0;
+       int ret;
+
+       if (!cal)
+               filter |= 0x10000;
+       if (dev->bw != MT_BW_20)
+               filter |= 0x00100;
+
+       /* TX */
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_BW, filter | 1);
+       if (ret)
+               return ret;
+       /* RX */
+       return mt7601u_mcu_calibrate(dev, MCU_CAL_BW, filter);
+}
+
+static int mt7601u_load_bbp_temp_table_bw(struct mt7601u_dev *dev)
+{
+       const struct reg_table *t;
+
+       if (WARN_ON(dev->temp_mode > MT_TEMP_MODE_LOW))
+               return -EINVAL;
+
+       t = &bbp_mode_table[dev->temp_mode][dev->bw];
+
+       return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, t->regs, t->n);
+}
+
+static int mt7601u_bbp_temp(struct mt7601u_dev *dev, int mode, const char *name)
+{
+       const struct reg_table *t;
+       int ret;
+
+       if (dev->temp_mode == mode)
+               return 0;
+
+       dev->temp_mode = mode;
+       trace_temp_mode(dev, mode);
+
+       t = bbp_mode_table[dev->temp_mode];
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
+                                     t[2].regs, t[2].n);
+       if (ret)
+               return ret;
+
+       return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
+                                      t[dev->bw].regs, t[dev->bw].n);
+}
+
+static void mt7601u_apply_ch14_fixup(struct mt7601u_dev *dev, int hw_chan)
+{
+       struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
+
+       if (hw_chan != 14 || dev->bw != MT_BW_20) {
+               mt7601u_bbp_rmw(dev, 4, 0x20, 0);
+               mt7601u_bbp_wr(dev, 178, 0xff);
+
+               t->cck[0].bw20 = dev->ee->real_cck_bw20[0];
+               t->cck[1].bw20 = dev->ee->real_cck_bw20[1];
+       } else { /* Apply CH14 OBW fixup */
+               mt7601u_bbp_wr(dev, 4, 0x60);
+               mt7601u_bbp_wr(dev, 178, 0);
+
+               /* Note: vendor code is buggy here for negative values */
+               t->cck[0].bw20 = dev->ee->real_cck_bw20[0] - 2;
+               t->cck[1].bw20 = dev->ee->real_cck_bw20[1] - 2;
+       }
+}
+
+static int __mt7601u_phy_set_channel(struct mt7601u_dev *dev,
+                                    struct cfg80211_chan_def *chandef)
+{
+#define FREQ_PLAN_REGS 4
+       static const u8 freq_plan[14][FREQ_PLAN_REGS] = {
+               { 0x99, 0x99,   0x09,   0x50 },
+               { 0x46, 0x44,   0x0a,   0x50 },
+               { 0xec, 0xee,   0x0a,   0x50 },
+               { 0x99, 0x99,   0x0b,   0x50 },
+               { 0x46, 0x44,   0x08,   0x51 },
+               { 0xec, 0xee,   0x08,   0x51 },
+               { 0x99, 0x99,   0x09,   0x51 },
+               { 0x46, 0x44,   0x0a,   0x51 },
+               { 0xec, 0xee,   0x0a,   0x51 },
+               { 0x99, 0x99,   0x0b,   0x51 },
+               { 0x46, 0x44,   0x08,   0x52 },
+               { 0xec, 0xee,   0x08,   0x52 },
+               { 0x99, 0x99,   0x09,   0x52 },
+               { 0x33, 0x33,   0x0b,   0x52 },
+       };
+       struct mt76_reg_pair channel_freq_plan[FREQ_PLAN_REGS] = {
+               { 17, 0 }, { 18, 0 }, { 19, 0 }, { 20, 0 },
+       };
+       struct mt76_reg_pair bbp_settings[3] = {
+               { 62, 0x37 - dev->ee->lna_gain },
+               { 63, 0x37 - dev->ee->lna_gain },
+               { 64, 0x37 - dev->ee->lna_gain },
+       };
+
+       struct ieee80211_channel *chan = chandef->chan;
+       enum nl80211_channel_type chan_type =
+               cfg80211_get_chandef_type(chandef);
+       struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
+       int chan_idx;
+       bool chan_ext_below;
+       u8 bw;
+       int i, ret;
+
+       bw = MT_BW_20;
+       chan_ext_below = (chan_type == NL80211_CHAN_HT40MINUS);
+       chan_idx = chan->hw_value - 1;
+
+       if (chandef->width == NL80211_CHAN_WIDTH_40) {
+               bw = MT_BW_40;
+
+               if (chan_idx > 1 && chan_type == NL80211_CHAN_HT40MINUS)
+                       chan_idx -= 2;
+               else if (chan_idx < 12 && chan_type == NL80211_CHAN_HT40PLUS)
+                       chan_idx += 2;
+               else
+                       dev_err(dev->dev, "Error: invalid 40MHz channel!!\n");
+       }
+
+       if (bw != dev->bw || chan_ext_below != dev->chan_ext_below) {
+               dev_dbg(dev->dev, "Info: switching HT mode bw:%d below:%d\n",
+                       bw, chan_ext_below);
+
+               mt7601u_bbp_set_bw(dev, bw);
+
+               mt7601u_bbp_set_ctrlch(dev, chan_ext_below);
+               mt7601u_mac_set_ctrlch(dev, chan_ext_below);
+               dev->chan_ext_below = chan_ext_below;
+       }
+
+       for (i = 0; i < FREQ_PLAN_REGS; i++)
+               channel_freq_plan[i].value = freq_plan[chan_idx][i];
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_RF,
+                                     channel_freq_plan, FREQ_PLAN_REGS);
+       if (ret)
+               return ret;
+
+       mt7601u_rmw(dev, MT_TX_ALC_CFG_0, 0x3f3f,
+                   dev->ee->chan_pwr[chan_idx] & 0x3f);
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
+                                     bbp_settings, ARRAY_SIZE(bbp_settings));
+       if (ret)
+               return ret;
+
+       mt7601u_vco_cal(dev);
+       mt7601u_bbp_set_bw(dev, bw);
+       ret = mt7601u_set_bw_filter(dev, false);
+       if (ret)
+               return ret;
+
+       mt7601u_apply_ch14_fixup(dev, chan->hw_value);
+       mt7601u_wr(dev, MT_TX_PWR_CFG_0, int_to_s6(t->ofdm[1].bw20) << 24 |
+                                        int_to_s6(t->ofdm[0].bw20) << 16 |
+                                        int_to_s6(t->cck[1].bw20) << 8 |
+                                        int_to_s6(t->cck[0].bw20));
+
+       if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
+               mt7601u_agc_reset(dev);
+
+       dev->chandef = *chandef;
+
+       return 0;
+}
+
+int mt7601u_phy_set_channel(struct mt7601u_dev *dev,
+                           struct cfg80211_chan_def *chandef)
+{
+       int ret;
+
+       cancel_delayed_work_sync(&dev->cal_work);
+       cancel_delayed_work_sync(&dev->freq_cal.work);
+
+       mutex_lock(&dev->hw_atomic_mutex);
+       ret = __mt7601u_phy_set_channel(dev, chandef);
+       mutex_unlock(&dev->hw_atomic_mutex);
+       if (ret)
+               return ret;
+
+       if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
+               return 0;
+
+       ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
+                                    MT_CALIBRATE_INTERVAL);
+       if (dev->freq_cal.enabled)
+               ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work,
+                                            MT_FREQ_CAL_INIT_DELAY);
+       return 0;
+}
+
+#define BBP_R47_FLAG           GENMASK(2, 0)
+#define BBP_R47_F_TSSI         0
+#define BBP_R47_F_PKT_T                1
+#define BBP_R47_F_TX_RATE      2
+#define BBP_R47_F_TEMP         4
+/**
+ * mt7601u_bbp_r47_get - read value through BBP R47/R49 pair
+ * @dev:       pointer to adapter structure
+ * @reg:       value of BBP R47 before the operation
+ * @flag:      one of the BBP_R47_F_* flags
+ *
+ * Convenience helper for reading values through BBP R47/R49 pair.
+ * Takes old value of BBP R47 as @reg, because callers usually have it
+ * cached already.
+ *
+ * Return: value of BBP R49.
+ */
+static u8 mt7601u_bbp_r47_get(struct mt7601u_dev *dev, u8 reg, u8 flag)
+{
+       flag |= reg & ~BBP_R47_FLAG;
+       mt7601u_bbp_wr(dev, 47, flag);
+       usleep_range(500, 700);
+       return mt7601u_bbp_rr(dev, 49);
+}
+
+static s8 mt7601u_read_bootup_temp(struct mt7601u_dev *dev)
+{
+       u8 bbp_val, temp;
+       u32 rf_bp, rf_set;
+       int i;
+
+       rf_set = mt7601u_rr(dev, MT_RF_SETTING_0);
+       rf_bp = mt7601u_rr(dev, MT_RF_BYPASS_0);
+
+       mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
+       mt7601u_wr(dev, MT_RF_SETTING_0, 0x00000010);
+       mt7601u_wr(dev, MT_RF_BYPASS_0, 0x00000010);
+
+       bbp_val = mt7601u_bbp_rmw(dev, 47, 0, 0x10);
+
+       mt7601u_bbp_wr(dev, 22, 0x40);
+
+       for (i = 100; i && (bbp_val & 0x10); i--)
+               bbp_val = mt7601u_bbp_rr(dev, 47);
+
+       temp = mt7601u_bbp_r47_get(dev, bbp_val, BBP_R47_F_TEMP);
+
+       mt7601u_bbp_wr(dev, 22, 0);
+
+       bbp_val = mt7601u_bbp_rr(dev, 21);
+       bbp_val |= 0x02;
+       mt7601u_bbp_wr(dev, 21, bbp_val);
+       bbp_val &= ~0x02;
+       mt7601u_bbp_wr(dev, 21, bbp_val);
+
+       mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
+       mt7601u_wr(dev, MT_RF_SETTING_0, rf_set);
+       mt7601u_wr(dev, MT_RF_BYPASS_0, rf_bp);
+
+       trace_read_temp(dev, temp);
+       return temp;
+}
+
+static s8 mt7601u_read_temp(struct mt7601u_dev *dev)
+{
+       int i;
+       u8 val;
+       s8 temp;
+
+       val = mt7601u_bbp_rmw(dev, 47, 0x7f, 0x10);
+
+       /* Note: this rarely succeeds, temp can change even if it fails. */
+       for (i = 100; i && (val & 0x10); i--)
+               val = mt7601u_bbp_rr(dev, 47);
+
+       temp = mt7601u_bbp_r47_get(dev, val, BBP_R47_F_TEMP);
+
+       trace_read_temp(dev, temp);
+       return temp;
+}
+
+static void mt7601u_rxdc_cal(struct mt7601u_dev *dev)
+{
+       static const struct mt76_reg_pair intro[] = {
+               { 158, 0x8d }, { 159, 0xfc },
+               { 158, 0x8c }, { 159, 0x4c },
+       }, outro[] = {
+               { 158, 0x8d }, { 159, 0xe0 },
+       };
+       u32 mac_ctrl;
+       int i, ret;
+
+       mac_ctrl = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX);
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
+                                     intro, ARRAY_SIZE(intro));
+       if (ret)
+               dev_err(dev->dev, "%s intro failed:%d\n", __func__, ret);
+
+       for (i = 20; i; i--) {
+               usleep_range(300, 500);
+
+               mt7601u_bbp_wr(dev, 158, 0x8c);
+               if (mt7601u_bbp_rr(dev, 159) == 0x0c)
+                       break;
+       }
+       if (!i)
+               dev_err(dev->dev, "%s timed out\n", __func__);
+
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
+
+       ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
+                                     outro, ARRAY_SIZE(outro));
+       if (ret)
+               dev_err(dev->dev, "%s outro failed:%d\n", __func__, ret);
+
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, mac_ctrl);
+}
+
+void mt7601u_phy_recalibrate_after_assoc(struct mt7601u_dev *dev)
+{
+       mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->curr_temp);
+
+       mt7601u_rxdc_cal(dev);
+}
+
+/* Note: function copied from vendor driver */
+static s16 lin2dBd(u16 linear)
+{
+       short exp = 0;
+       unsigned int mantisa;
+       int app, dBd;
+
+       if (WARN_ON(!linear))
+               return -10000;
+
+       mantisa = linear;
+
+       exp = fls(mantisa) - 16;
+       if (exp > 0)
+               mantisa >>= exp;
+       else
+               mantisa <<= abs(exp);
+
+       if (mantisa <= 0xb800)
+               app = (mantisa + (mantisa >> 3) + (mantisa >> 4) - 0x9600);
+       else
+               app = (mantisa - (mantisa >> 3) - (mantisa >> 6) - 0x5a00);
+       if (app < 0)
+               app = 0;
+
+       dBd = ((15 + exp) << 15) + app;
+       dBd = (dBd << 2) + (dBd << 1) + (dBd >> 6) + (dBd >> 7);
+       dBd = (dBd >> 10);
+
+       return dBd;
+}
+
+static void
+mt7601u_set_initial_tssi(struct mt7601u_dev *dev, s16 tssi_db, s16 tssi_hvga_db)
+{
+       struct tssi_data *d = &dev->ee->tssi_data;
+       int init_offset;
+
+       init_offset = -((tssi_db * d->slope + d->offset[1]) / 4096) + 10;
+
+       mt76_rmw(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
+                int_to_s6(init_offset) & MT_TX_ALC_CFG_1_TEMP_COMP);
+}
+
+static void mt7601u_tssi_dc_gain_cal(struct mt7601u_dev *dev)
+{
+       u8 rf_vga, rf_mixer, bbp_r47;
+       int i, j;
+       s8 res[4];
+       s16 tssi_init_db, tssi_init_hvga_db;
+
+       mt7601u_wr(dev, MT_RF_SETTING_0, 0x00000030);
+       mt7601u_wr(dev, MT_RF_BYPASS_0, 0x000c0030);
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
+
+       mt7601u_bbp_wr(dev, 58, 0);
+       mt7601u_bbp_wr(dev, 241, 0x2);
+       mt7601u_bbp_wr(dev, 23, 0x8);
+       bbp_r47 = mt7601u_bbp_rr(dev, 47);
+
+       /* Set VGA gain */
+       rf_vga = mt7601u_rf_rr(dev, 5, 3);
+       mt7601u_rf_wr(dev, 5, 3, 8);
+
+       /* Mixer disable */
+       rf_mixer = mt7601u_rf_rr(dev, 4, 39);
+       mt7601u_rf_wr(dev, 4, 39, 0);
+
+       for (i = 0; i < 4; i++) {
+               mt7601u_rf_wr(dev, 4, 39, (i & 1) ? rf_mixer : 0);
+
+               mt7601u_bbp_wr(dev, 23, (i < 2) ? 0x08 : 0x02);
+               mt7601u_rf_wr(dev, 5, 3, (i < 2) ? 0x08 : 0x11);
+
+               /* BBP TSSI initial and soft reset */
+               mt7601u_bbp_wr(dev, 22, 0);
+               mt7601u_bbp_wr(dev, 244, 0);
+
+               mt7601u_bbp_wr(dev, 21, 1);
+               udelay(1);
+               mt7601u_bbp_wr(dev, 21, 0);
+
+               /* TSSI measurement */
+               mt7601u_bbp_wr(dev, 47, 0x50);
+               mt7601u_bbp_wr(dev, (i & 1) ? 244 : 22, (i & 1) ? 0x31 : 0x40);
+
+               for (j = 20; j; j--)
+                       if (!(mt7601u_bbp_rr(dev, 47) & 0x10))
+                               break;
+               if (!j)
+                       dev_err(dev->dev, "%s timed out\n", __func__);
+
+               /* TSSI read */
+               mt7601u_bbp_wr(dev, 47, 0x40);
+               res[i] = mt7601u_bbp_rr(dev, 49);
+       }
+
+       tssi_init_db = lin2dBd((short)res[1] - res[0]);
+       tssi_init_hvga_db = lin2dBd(((short)res[3] - res[2]) * 4);
+       dev->tssi_init = res[0];
+       dev->tssi_init_hvga = res[2];
+       dev->tssi_init_hvga_offset_db = tssi_init_hvga_db - tssi_init_db;
+
+       dev_dbg(dev->dev,
+               "TSSI_init:%hhx db:%hx hvga:%hhx hvga_db:%hx off_db:%hx\n",
+               dev->tssi_init, tssi_init_db, dev->tssi_init_hvga,
+               tssi_init_hvga_db, dev->tssi_init_hvga_offset_db);
+
+       mt7601u_bbp_wr(dev, 22, 0);
+       mt7601u_bbp_wr(dev, 244, 0);
+
+       mt7601u_bbp_wr(dev, 21, 1);
+       udelay(1);
+       mt7601u_bbp_wr(dev, 21, 0);
+
+       mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
+       mt7601u_wr(dev, MT_RF_SETTING_0, 0);
+
+       mt7601u_rf_wr(dev, 5, 3, rf_vga);
+       mt7601u_rf_wr(dev, 4, 39, rf_mixer);
+       mt7601u_bbp_wr(dev, 47, bbp_r47);
+
+       mt7601u_set_initial_tssi(dev, tssi_init_db, tssi_init_hvga_db);
+}
+
+static int mt7601u_temp_comp(struct mt7601u_dev *dev, bool on)
+{
+       int ret, temp, hi_temp = 400, lo_temp = -200;
+
+       temp = (dev->raw_temp - dev->ee->ref_temp) * MT_EE_TEMPERATURE_SLOPE;
+       dev->curr_temp = temp;
+
+       /* DPD Calibration */
+       if (temp - dev->dpd_temp > 450 || temp - dev->dpd_temp < -450) {
+               dev->dpd_temp = temp;
+
+               ret = mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->dpd_temp);
+               if (ret)
+                       return ret;
+
+               mt7601u_vco_cal(dev);
+
+               dev_dbg(dev->dev, "Recalibrate DPD\n");
+       }
+
+       /* PLL Lock Protect */
+       if (temp < -50 && !dev->pll_lock_protect) { /* < 20C */
+               dev->pll_lock_protect =  true;
+
+               mt7601u_rf_wr(dev, 4, 4, 6);
+               mt7601u_rf_clear(dev, 4, 10, 0x30);
+
+               dev_dbg(dev->dev, "PLL lock protect on - too cold\n");
+       } else if (temp > 50 && dev->pll_lock_protect) { /* > 30C */
+               dev->pll_lock_protect = false;
+
+               mt7601u_rf_wr(dev, 4, 4, 0);
+               mt7601u_rf_rmw(dev, 4, 10, 0x30, 0x10);
+
+               dev_dbg(dev->dev, "PLL lock protect off\n");
+       }
+
+       if (on) {
+               hi_temp -= 50;
+               lo_temp -= 50;
+       }
+
+       /* BBP CR for H, L, N temperature */
+       if (temp > hi_temp)
+               return mt7601u_bbp_temp(dev, MT_TEMP_MODE_HIGH, "high");
+       else if (temp > lo_temp)
+               return mt7601u_bbp_temp(dev, MT_TEMP_MODE_NORMAL, "normal");
+       else
+               return mt7601u_bbp_temp(dev, MT_TEMP_MODE_LOW, "low");
+}
+
+/* Note: this is used only with TSSI, we can just use trgt_pwr from eeprom. */
+static int mt7601u_current_tx_power(struct mt7601u_dev *dev)
+{
+       return dev->ee->chan_pwr[dev->chandef.chan->hw_value - 1];
+}
+
+static bool mt7601u_use_hvga(struct mt7601u_dev *dev)
+{
+       return !(mt7601u_current_tx_power(dev) > 20);
+}
+
+static s16
+mt7601u_phy_rf_pa_mode_val(struct mt7601u_dev *dev, int phy_mode, int tx_rate)
+{
+       static const s16 decode_tb[] = { 0, 8847, -5734, -5734 };
+       u32 reg;
+
+       switch (phy_mode) {
+       case MT_PHY_TYPE_OFDM:
+               tx_rate += 4;
+       case MT_PHY_TYPE_CCK:
+               reg = dev->rf_pa_mode[0];
+               break;
+       default:
+               reg = dev->rf_pa_mode[1];
+               break;
+       }
+
+       return decode_tb[(reg >> (tx_rate * 2)) & 0x3];
+}
+
+static struct mt7601u_tssi_params
+mt7601u_tssi_params_get(struct mt7601u_dev *dev)
+{
+       static const u8 ofdm_pkt2rate[8] = { 6, 4, 2, 0, 7, 5, 3, 1 };
+       static const int static_power[4] = { 0, -49152, -98304, 49152 };
+       struct mt7601u_tssi_params p;
+       u8 bbp_r47, pkt_type, tx_rate;
+       struct power_per_rate *rate_table;
+
+       bbp_r47 = mt7601u_bbp_rr(dev, 47);
+
+       p.tssi0 = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TSSI);
+       dev->raw_temp = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TEMP);
+       pkt_type = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_PKT_T);
+
+       p.trgt_power = mt7601u_current_tx_power(dev);
+
+       switch (pkt_type & 0x03) {
+       case MT_PHY_TYPE_CCK:
+               tx_rate = (pkt_type >> 4) & 0x03;
+               rate_table = dev->ee->power_rate_table.cck;
+               break;
+
+       case MT_PHY_TYPE_OFDM:
+               tx_rate = ofdm_pkt2rate[(pkt_type >> 4) & 0x07];
+               rate_table = dev->ee->power_rate_table.ofdm;
+               break;
+
+       default:
+               tx_rate = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TX_RATE);
+               tx_rate &= 0x7f;
+               rate_table = dev->ee->power_rate_table.ht;
+               break;
+       }
+
+       if (dev->bw == MT_BW_20)
+               p.trgt_power += rate_table[tx_rate / 2].bw20;
+       else
+               p.trgt_power += rate_table[tx_rate / 2].bw40;
+
+       p.trgt_power <<= 12;
+
+       dev_dbg(dev->dev, "tx_rate:%02hhx pwr:%08x\n", tx_rate, p.trgt_power);
+
+       p.trgt_power += mt7601u_phy_rf_pa_mode_val(dev, pkt_type & 0x03,
+                                                  tx_rate);
+
+       /* Channel 14, cck, bw20 */
+       if ((pkt_type & 0x03) == MT_PHY_TYPE_CCK) {
+               if (mt7601u_bbp_rr(dev, 4) & 0x20)
+                       p.trgt_power += mt7601u_bbp_rr(dev, 178) ? 18022 : 9830;
+               else
+                       p.trgt_power += mt7601u_bbp_rr(dev, 178) ? 819 : 24576;
+       }
+
+       p.trgt_power += static_power[mt7601u_bbp_rr(dev, 1) & 0x03];
+
+       p.trgt_power += dev->ee->tssi_data.tx0_delta_offset;
+
+       dev_dbg(dev->dev,
+               "tssi:%02hhx t_power:%08x temp:%02hhx pkt_type:%02hhx\n",
+               p.tssi0, p.trgt_power, dev->raw_temp, pkt_type);
+
+       return p;
+}
+
+static bool mt7601u_tssi_read_ready(struct mt7601u_dev *dev)
+{
+       return !(mt7601u_bbp_rr(dev, 47) & 0x10);
+}
+
+static int mt7601u_tssi_cal(struct mt7601u_dev *dev)
+{
+       struct mt7601u_tssi_params params;
+       int curr_pwr, diff_pwr;
+       char tssi_offset;
+       s8 tssi_init;
+       s16 tssi_m_dc, tssi_db;
+       bool hvga;
+       u32 val;
+
+       if (!dev->ee->tssi_enabled)
+               return 0;
+
+       hvga = mt7601u_use_hvga(dev);
+       if (!dev->tssi_read_trig)
+               return mt7601u_mcu_tssi_read_kick(dev, hvga);
+
+       if (!mt7601u_tssi_read_ready(dev))
+               return 0;
+
+       params = mt7601u_tssi_params_get(dev);
+
+       tssi_init = (hvga ? dev->tssi_init_hvga : dev->tssi_init);
+       tssi_m_dc = params.tssi0 - tssi_init;
+       tssi_db = lin2dBd(tssi_m_dc);
+       dev_dbg(dev->dev, "tssi dc:%04hx db:%04hx hvga:%d\n",
+               tssi_m_dc, tssi_db, hvga);
+
+       if (dev->chandef.chan->hw_value < 5)
+               tssi_offset = dev->ee->tssi_data.offset[0];
+       else if (dev->chandef.chan->hw_value < 9)
+               tssi_offset = dev->ee->tssi_data.offset[1];
+       else
+               tssi_offset = dev->ee->tssi_data.offset[2];
+
+       if (hvga)
+               tssi_db -= dev->tssi_init_hvga_offset_db;
+
+       curr_pwr = tssi_db * dev->ee->tssi_data.slope + (tssi_offset << 9);
+       diff_pwr = params.trgt_power - curr_pwr;
+       dev_dbg(dev->dev, "Power curr:%08x diff:%08x\n", curr_pwr, diff_pwr);
+
+       if (params.tssi0 > 126 && diff_pwr > 0) {
+               dev_err(dev->dev, "Error: TSSI upper saturation\n");
+               diff_pwr = 0;
+       }
+       if (params.tssi0 - tssi_init < 1 && diff_pwr < 0) {
+               dev_err(dev->dev, "Error: TSSI lower saturation\n");
+               diff_pwr = 0;
+       }
+
+       if ((dev->prev_pwr_diff ^ diff_pwr) < 0 && abs(diff_pwr) < 4096 &&
+           (abs(diff_pwr) > abs(dev->prev_pwr_diff) ||
+            (diff_pwr > 0 && diff_pwr == -dev->prev_pwr_diff)))
+               diff_pwr = 0;
+       else
+               dev->prev_pwr_diff = diff_pwr;
+
+       diff_pwr += (diff_pwr > 0) ? 2048 : -2048;
+       diff_pwr /= 4096;
+
+       dev_dbg(dev->dev, "final diff: %08x\n", diff_pwr);
+
+       val = mt7601u_rr(dev, MT_TX_ALC_CFG_1);
+       curr_pwr = s6_to_int(MT76_GET(MT_TX_ALC_CFG_1_TEMP_COMP, val));
+       diff_pwr += curr_pwr;
+       val = (val & ~MT_TX_ALC_CFG_1_TEMP_COMP) | int_to_s6(diff_pwr);
+       mt7601u_wr(dev, MT_TX_ALC_CFG_1, val);
+
+       return mt7601u_mcu_tssi_read_kick(dev, hvga);
+}
+
+static u8 mt7601u_agc_default(struct mt7601u_dev *dev)
+{
+       return (dev->ee->lna_gain - 8) * 2 + 0x34;
+}
+
+static void mt7601u_agc_reset(struct mt7601u_dev *dev)
+{
+       u8 agc = mt7601u_agc_default(dev);
+
+       mt7601u_bbp_wr(dev, 66, agc);
+}
+
+void mt7601u_agc_save(struct mt7601u_dev *dev)
+{
+       dev->agc_save = mt7601u_bbp_rr(dev, 66);
+}
+
+void mt7601u_agc_restore(struct mt7601u_dev *dev)
+{
+       mt7601u_bbp_wr(dev, 66, dev->agc_save);
+}
+
+static void mt7601u_agc_tune(struct mt7601u_dev *dev)
+{
+       u8 val = mt7601u_agc_default(dev);
+
+       if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
+               return;
+
+       /* Note: only in STA mode and not dozing; perhaps do this only if
+        *       there is enough rssi updates since last run?
+        *       Rssi updates are only on beacons and U2M so should work...
+        */
+       spin_lock_bh(&dev->con_mon_lock);
+       if (dev->avg_rssi <= -70)
+               val -= 0x20;
+       else if (dev->avg_rssi <= -60)
+               val -= 0x10;
+       spin_unlock_bh(&dev->con_mon_lock);
+
+       if (val != mt7601u_bbp_rr(dev, 66))
+               mt7601u_bbp_wr(dev, 66, val);
+
+       /* TODO: also if lost a lot of beacons try resetting
+        *       (see RTMPSetAGCInitValue() call in mlme.c).
+        */
+}
+
+static void mt7601u_phy_calibrate(struct work_struct *work)
+{
+       struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
+                                           cal_work.work);
+
+       mt7601u_agc_tune(dev);
+       mt7601u_tssi_cal(dev);
+       /* If TSSI calibration was run it already updated temperature. */
+       if (!dev->ee->tssi_enabled)
+               dev->raw_temp = mt7601u_read_temp(dev);
+       mt7601u_temp_comp(dev, true); /* TODO: find right value for @on */
+
+       ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
+                                    MT_CALIBRATE_INTERVAL);
+}
+
+static unsigned long
+__mt7601u_phy_freq_cal(struct mt7601u_dev *dev, s8 last_offset, u8 phy_mode)
+{
+       u8 activate_threshold, deactivate_threshold;
+
+       trace_freq_cal_offset(dev, phy_mode, last_offset);
+
+       /* No beacons received - reschedule soon */
+       if (last_offset == MT_FREQ_OFFSET_INVALID)
+               return MT_FREQ_CAL_ADJ_INTERVAL;
+
+       switch (phy_mode) {
+       case MT_PHY_TYPE_CCK:
+               activate_threshold = 19;
+               deactivate_threshold = 5;
+               break;
+       case MT_PHY_TYPE_OFDM:
+               activate_threshold = 102;
+               deactivate_threshold = 32;
+               break;
+       case MT_PHY_TYPE_HT:
+       case MT_PHY_TYPE_HT_GF:
+               activate_threshold = 82;
+               deactivate_threshold = 20;
+               break;
+       default:
+               WARN_ON(1);
+               return MT_FREQ_CAL_CHECK_INTERVAL;
+       }
+
+       if (abs(last_offset) >= activate_threshold)
+               dev->freq_cal.adjusting = true;
+       else if (abs(last_offset) <= deactivate_threshold)
+               dev->freq_cal.adjusting = false;
+
+       if (!dev->freq_cal.adjusting)
+               return MT_FREQ_CAL_CHECK_INTERVAL;
+
+       if (last_offset > deactivate_threshold) {
+               if (dev->freq_cal.freq > 0)
+                       dev->freq_cal.freq--;
+               else
+                       dev->freq_cal.adjusting = false;
+       } else if (last_offset < -deactivate_threshold) {
+               if (dev->freq_cal.freq < 0xbf)
+                       dev->freq_cal.freq++;
+               else
+                       dev->freq_cal.adjusting = false;
+       }
+
+       trace_freq_cal_adjust(dev, dev->freq_cal.freq);
+       mt7601u_rf_wr(dev, 0, 12, dev->freq_cal.freq);
+       mt7601u_vco_cal(dev);
+
+       return dev->freq_cal.adjusting ? MT_FREQ_CAL_ADJ_INTERVAL :
+                                        MT_FREQ_CAL_CHECK_INTERVAL;
+}
+
+static void mt7601u_phy_freq_cal(struct work_struct *work)
+{
+       struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
+                                              freq_cal.work.work);
+       s8 last_offset;
+       u8 phy_mode;
+       unsigned long delay;
+
+       spin_lock_bh(&dev->con_mon_lock);
+       last_offset = dev->bcn_freq_off;
+       phy_mode = dev->bcn_phy_mode;
+       spin_unlock_bh(&dev->con_mon_lock);
+
+       delay = __mt7601u_phy_freq_cal(dev, last_offset, phy_mode);
+       ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work, delay);
+
+       spin_lock_bh(&dev->con_mon_lock);
+       dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
+       spin_unlock_bh(&dev->con_mon_lock);
+}
+
+void mt7601u_phy_con_cal_onoff(struct mt7601u_dev *dev,
+                              struct ieee80211_bss_conf *info)
+{
+       if (!info->assoc)
+               cancel_delayed_work_sync(&dev->freq_cal.work);
+
+       /* Start/stop collecting beacon data */
+       spin_lock_bh(&dev->con_mon_lock);
+       ether_addr_copy(dev->ap_bssid, info->bssid);
+       dev->avg_rssi = 0;
+       dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
+       spin_unlock_bh(&dev->con_mon_lock);
+
+       dev->freq_cal.freq = dev->ee->rf_freq_off;
+       dev->freq_cal.enabled = info->assoc;
+       dev->freq_cal.adjusting = false;
+
+       if (info->assoc)
+               ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work,
+                                            MT_FREQ_CAL_INIT_DELAY);
+}
+
+static int mt7601u_init_cal(struct mt7601u_dev *dev)
+{
+       u32 mac_ctrl;
+       int ret;
+
+       dev->raw_temp = mt7601u_read_bootup_temp(dev);
+       dev->curr_temp = (dev->raw_temp - dev->ee->ref_temp) *
+               MT_EE_TEMPERATURE_SLOPE;
+       dev->dpd_temp = dev->curr_temp;
+
+       mac_ctrl = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
+
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_R, 0);
+       if (ret)
+               return ret;
+
+       ret = mt7601u_rf_rr(dev, 0, 4);
+       if (ret < 0)
+               return ret;
+       ret |= 0x80;
+       ret = mt7601u_rf_wr(dev, 0, 4, ret);
+       if (ret)
+               return ret;
+       msleep(2);
+
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_TXDCOC, 0);
+       if (ret)
+               return ret;
+
+       mt7601u_rxdc_cal(dev);
+
+       ret = mt7601u_set_bw_filter(dev, true);
+       if (ret)
+               return ret;
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_LOFT, 0);
+       if (ret)
+               return ret;
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_TXIQ, 0);
+       if (ret)
+               return ret;
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_RXIQ, 0);
+       if (ret)
+               return ret;
+       ret = mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->dpd_temp);
+       if (ret)
+               return ret;
+
+       mt7601u_rxdc_cal(dev);
+
+       mt7601u_tssi_dc_gain_cal(dev);
+
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, mac_ctrl);
+
+       mt7601u_temp_comp(dev, true);
+
+       return 0;
+}
+
+int mt7601u_bbp_set_bw(struct mt7601u_dev *dev, int bw)
+{
+       u32 val, old;
+
+       if (bw == dev->bw) {
+               /* Vendor driver does the rmc even when no change is needed. */
+               mt7601u_bbp_rmc(dev, 4, 0x18, bw == MT_BW_20 ? 0 : 0x10);
+
+               return 0;
+       }
+       dev->bw = bw;
+
+       /* Stop MAC for the time of bw change */
+       old = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
+       val = old & ~(MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, val);
+       mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
+                 0, 500000);
+
+       mt7601u_bbp_rmc(dev, 4, 0x18, bw == MT_BW_20 ? 0 : 0x10);
+
+       mt7601u_wr(dev, MT_MAC_SYS_CTRL, old);
+
+       return mt7601u_load_bbp_temp_table_bw(dev);
+}
+
+/**
+ * mt7601u_set_rx_path - set rx path in BBP
+ * @dev:       pointer to adapter structure
+ * @path:      rx path to set values are 0-based
+ */
+void mt7601u_set_rx_path(struct mt7601u_dev *dev, u8 path)
+{
+       mt7601u_bbp_rmw(dev, 3, 0x18, path << 3);
+}
+
+/**
+ * mt7601u_set_tx_dac - set which tx DAC to use
+ * @dev:       pointer to adapter structure
+ * @path:      DAC index, values are 0-based
+ */
+void mt7601u_set_tx_dac(struct mt7601u_dev *dev, u8 dac)
+{
+       mt7601u_bbp_rmc(dev, 1, 0x18, dac << 3);
+}
+
+int mt7601u_phy_init(struct mt7601u_dev *dev)
+{
+       int ret;
+
+       dev->rf_pa_mode[0] = mt7601u_rr(dev, MT_RF_PA_MODE_CFG0);
+       dev->rf_pa_mode[1] = mt7601u_rr(dev, MT_RF_PA_MODE_CFG1);
+
+       ret = mt7601u_rf_wr(dev, 0, 12, dev->ee->rf_freq_off);
+       if (ret)
+               return ret;
+       ret = mt7601u_write_reg_pairs(dev, 0, rf_central,
+                                     ARRAY_SIZE(rf_central));
+       if (ret)
+               return ret;
+       ret = mt7601u_write_reg_pairs(dev, 0, rf_channel,
+                                     ARRAY_SIZE(rf_channel));
+       if (ret)
+               return ret;
+       ret = mt7601u_write_reg_pairs(dev, 0, rf_vga, ARRAY_SIZE(rf_vga));
+       if (ret)
+               return ret;
+
+       ret = mt7601u_init_cal(dev);
+       if (ret)
+               return ret;
+
+       dev->prev_pwr_diff = 100;
+
+       INIT_DELAYED_WORK(&dev->cal_work, mt7601u_phy_calibrate);
+       INIT_DELAYED_WORK(&dev->freq_cal.work, mt7601u_phy_freq_cal);
+
+       return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/regs.h b/drivers/net/wireless/mediatek/mt7601u/regs.h
new file mode 100644 (file)
index 0000000..afd8978
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT76_REGS_H
+#define __MT76_REGS_H
+
+#include <linux/bitops.h>
+
+#ifndef GENMASK
+#define GENMASK(h, l)       (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
+#endif
+
+#define MT_ASIC_VERSION                        0x0000
+
+#define MT76XX_REV_E3          0x22
+#define MT76XX_REV_E4          0x33
+
+#define MT_CMB_CTRL                    0x0020
+#define MT_CMB_CTRL_XTAL_RDY           BIT(22)
+#define MT_CMB_CTRL_PLL_LD             BIT(23)
+
+#define MT_EFUSE_CTRL                  0x0024
+#define MT_EFUSE_CTRL_AOUT             GENMASK(5, 0)
+#define MT_EFUSE_CTRL_MODE             GENMASK(7, 6)
+#define MT_EFUSE_CTRL_LDO_OFF_TIME     GENMASK(13, 8)
+#define MT_EFUSE_CTRL_LDO_ON_TIME      GENMASK(15, 14)
+#define MT_EFUSE_CTRL_AIN              GENMASK(25, 16)
+#define MT_EFUSE_CTRL_KICK             BIT(30)
+#define MT_EFUSE_CTRL_SEL              BIT(31)
+
+#define MT_EFUSE_DATA_BASE             0x0028
+#define MT_EFUSE_DATA(_n)              (MT_EFUSE_DATA_BASE + ((_n) << 2))
+
+#define MT_COEXCFG0                    0x0040
+#define MT_COEXCFG0_COEX_EN            BIT(0)
+
+#define MT_WLAN_FUN_CTRL               0x0080
+#define MT_WLAN_FUN_CTRL_WLAN_EN       BIT(0)
+#define MT_WLAN_FUN_CTRL_WLAN_CLK_EN   BIT(1)
+#define MT_WLAN_FUN_CTRL_WLAN_RESET_RF BIT(2)
+
+#define MT_WLAN_FUN_CTRL_WLAN_RESET    BIT(3) /* MT76x0 */
+#define MT_WLAN_FUN_CTRL_CSR_F20M_CKEN BIT(3) /* MT76x2 */
+
+#define MT_WLAN_FUN_CTRL_PCIE_CLK_REQ  BIT(4)
+#define MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL        BIT(5)
+#define MT_WLAN_FUN_CTRL_INV_ANT_SEL   BIT(6)
+#define MT_WLAN_FUN_CTRL_WAKE_HOST     BIT(7)
+
+#define MT_WLAN_FUN_CTRL_THERM_RST     BIT(8) /* MT76x2 */
+#define MT_WLAN_FUN_CTRL_THERM_CKEN    BIT(9) /* MT76x2 */
+
+#define MT_WLAN_FUN_CTRL_GPIO_IN       GENMASK(15, 8) /* MT76x0 */
+#define MT_WLAN_FUN_CTRL_GPIO_OUT      GENMASK(23, 16) /* MT76x0 */
+#define MT_WLAN_FUN_CTRL_GPIO_OUT_EN   GENMASK(31, 24) /* MT76x0 */
+
+#define MT_XO_CTRL0                    0x0100
+#define MT_XO_CTRL1                    0x0104
+#define MT_XO_CTRL2                    0x0108
+#define MT_XO_CTRL3                    0x010c
+#define MT_XO_CTRL4                    0x0110
+
+#define MT_XO_CTRL5                    0x0114
+#define MT_XO_CTRL5_C2_VAL             GENMASK(14, 8)
+
+#define MT_XO_CTRL6                    0x0118
+#define MT_XO_CTRL6_C2_CTRL            GENMASK(14, 8)
+
+#define MT_XO_CTRL7                    0x011c
+
+#define MT_WLAN_MTC_CTRL               0x10148
+#define MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP BIT(0)
+#define MT_WLAN_MTC_CTRL_PWR_ACK       BIT(12)
+#define MT_WLAN_MTC_CTRL_PWR_ACK_S     BIT(13)
+#define MT_WLAN_MTC_CTRL_BBP_MEM_PD    GENMASK(19, 16)
+#define MT_WLAN_MTC_CTRL_PBF_MEM_PD    BIT(20)
+#define MT_WLAN_MTC_CTRL_FCE_MEM_PD    BIT(21)
+#define MT_WLAN_MTC_CTRL_TSO_MEM_PD    BIT(22)
+#define MT_WLAN_MTC_CTRL_BBP_MEM_RB    BIT(24)
+#define MT_WLAN_MTC_CTRL_PBF_MEM_RB    BIT(25)
+#define MT_WLAN_MTC_CTRL_FCE_MEM_RB    BIT(26)
+#define MT_WLAN_MTC_CTRL_TSO_MEM_RB    BIT(27)
+#define MT_WLAN_MTC_CTRL_STATE_UP      BIT(28)
+
+#define MT_INT_SOURCE_CSR              0x0200
+#define MT_INT_MASK_CSR                        0x0204
+
+#define MT_INT_RX_DONE(_n)             BIT(_n)
+#define MT_INT_RX_DONE_ALL             GENMASK(1, 0)
+#define MT_INT_TX_DONE_ALL             GENMASK(13, 4)
+#define MT_INT_TX_DONE(_n)             BIT(_n + 4)
+#define MT_INT_RX_COHERENT             BIT(16)
+#define MT_INT_TX_COHERENT             BIT(17)
+#define MT_INT_ANY_COHERENT            BIT(18)
+#define MT_INT_MCU_CMD                 BIT(19)
+#define MT_INT_TBTT                    BIT(20)
+#define MT_INT_PRE_TBTT                        BIT(21)
+#define MT_INT_TX_STAT                 BIT(22)
+#define MT_INT_AUTO_WAKEUP             BIT(23)
+#define MT_INT_GPTIMER                 BIT(24)
+#define MT_INT_RXDELAYINT              BIT(26)
+#define MT_INT_TXDELAYINT              BIT(27)
+
+#define MT_WPDMA_GLO_CFG               0x0208
+#define MT_WPDMA_GLO_CFG_TX_DMA_EN     BIT(0)
+#define MT_WPDMA_GLO_CFG_TX_DMA_BUSY   BIT(1)
+#define MT_WPDMA_GLO_CFG_RX_DMA_EN     BIT(2)
+#define MT_WPDMA_GLO_CFG_RX_DMA_BUSY   BIT(3)
+#define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE        GENMASK(5, 4)
+#define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE     BIT(6)
+#define MT_WPDMA_GLO_CFG_BIG_ENDIAN    BIT(7)
+#define MT_WPDMA_GLO_CFG_HDR_SEG_LEN   GENMASK(15, 8)
+#define MT_WPDMA_GLO_CFG_CLK_GATE_DIS  BIT(30)
+#define MT_WPDMA_GLO_CFG_RX_2B_OFFSET  BIT(31)
+
+#define MT_WPDMA_RST_IDX               0x020c
+
+#define MT_WPDMA_DELAY_INT_CFG         0x0210
+
+#define MT_WMM_AIFSN           0x0214
+#define MT_WMM_AIFSN_MASK              GENMASK(3, 0)
+#define MT_WMM_AIFSN_SHIFT(_n)         ((_n) * 4)
+
+#define MT_WMM_CWMIN           0x0218
+#define MT_WMM_CWMIN_MASK              GENMASK(3, 0)
+#define MT_WMM_CWMIN_SHIFT(_n)         ((_n) * 4)
+
+#define MT_WMM_CWMAX           0x021c
+#define MT_WMM_CWMAX_MASK              GENMASK(3, 0)
+#define MT_WMM_CWMAX_SHIFT(_n)         ((_n) * 4)
+
+#define MT_WMM_TXOP_BASE               0x0220
+#define MT_WMM_TXOP(_n)                        (MT_WMM_TXOP_BASE + (((_n) / 2) << 2))
+#define MT_WMM_TXOP_SHIFT(_n)          ((_n & 1) * 16)
+#define MT_WMM_TXOP_MASK               GENMASK(15, 0)
+
+#define MT_FCE_DMA_ADDR                        0x0230
+#define MT_FCE_DMA_LEN                 0x0234
+
+#define MT_USB_DMA_CFG                 0x238
+#define MT_USB_DMA_CFG_RX_BULK_AGG_TOUT        GENMASK(7, 0)
+#define MT_USB_DMA_CFG_RX_BULK_AGG_LMT GENMASK(15, 8)
+#define MT_USB_DMA_CFG_PHY_CLR         BIT(16)
+#define MT_USB_DMA_CFG_TX_CLR          BIT(19)
+#define MT_USB_DMA_CFG_TXOP_HALT       BIT(20)
+#define MT_USB_DMA_CFG_RX_BULK_AGG_EN  BIT(21)
+#define MT_USB_DMA_CFG_RX_BULK_EN      BIT(22)
+#define MT_USB_DMA_CFG_TX_BULK_EN      BIT(23)
+#define MT_USB_DMA_CFG_UDMA_RX_WL_DROP BIT(25)
+#define MT_USB_DMA_CFG_EP_OUT_VALID    GENMASK(29, 27)
+#define MT_USB_DMA_CFG_RX_BUSY         BIT(30)
+#define MT_USB_DMA_CFG_TX_BUSY         BIT(31)
+
+#define MT_TSO_CTRL                    0x0250
+#define MT_HEADER_TRANS_CTRL_REG       0x0260
+
+#define MT_US_CYC_CFG                  0x02a4
+#define MT_US_CYC_CNT                  GENMASK(7, 0)
+
+#define MT_TX_RING_BASE                        0x0300
+#define MT_RX_RING_BASE                        0x03c0
+#define MT_RING_SIZE                   0x10
+
+#define MT_TX_HW_QUEUE_MCU             8
+#define MT_TX_HW_QUEUE_MGMT            9
+
+#define MT_PBF_SYS_CTRL                        0x0400
+#define MT_PBF_SYS_CTRL_MCU_RESET      BIT(0)
+#define MT_PBF_SYS_CTRL_DMA_RESET      BIT(1)
+#define MT_PBF_SYS_CTRL_MAC_RESET      BIT(2)
+#define MT_PBF_SYS_CTRL_PBF_RESET      BIT(3)
+#define MT_PBF_SYS_CTRL_ASY_RESET      BIT(4)
+
+#define MT_PBF_CFG                     0x0404
+#define MT_PBF_CFG_TX0Q_EN             BIT(0)
+#define MT_PBF_CFG_TX1Q_EN             BIT(1)
+#define MT_PBF_CFG_TX2Q_EN             BIT(2)
+#define MT_PBF_CFG_TX3Q_EN             BIT(3)
+#define MT_PBF_CFG_RX0Q_EN             BIT(4)
+#define MT_PBF_CFG_RX_DROP_EN          BIT(8)
+
+#define MT_PBF_TX_MAX_PCNT             0x0408
+#define MT_PBF_RX_MAX_PCNT             0x040c
+
+#define MT_BCN_OFFSET_BASE             0x041c
+#define MT_BCN_OFFSET(_n)              (MT_BCN_OFFSET_BASE + ((_n) << 2))
+
+#define        MT_RF_CSR_CFG                   0x0500
+#define MT_RF_CSR_CFG_DATA             GENMASK(7, 0)
+#define MT_RF_CSR_CFG_REG_ID           GENMASK(13, 8)
+#define MT_RF_CSR_CFG_REG_BANK         GENMASK(17, 14)
+#define MT_RF_CSR_CFG_WR               BIT(30)
+#define MT_RF_CSR_CFG_KICK             BIT(31)
+
+#define MT_RF_BYPASS_0                 0x0504
+#define MT_RF_BYPASS_1                 0x0508
+#define MT_RF_SETTING_0                        0x050c
+
+#define MT_RF_DATA_WRITE               0x0524
+
+#define MT_RF_CTRL                     0x0528
+#define MT_RF_CTRL_ADDR                        GENMASK(11, 0)
+#define MT_RF_CTRL_WRITE               BIT(12)
+#define MT_RF_CTRL_BUSY                        BIT(13)
+#define MT_RF_CTRL_IDX                 BIT(16)
+
+#define MT_RF_DATA_READ                        0x052c
+
+#define MT_FCE_PSE_CTRL                        0x0800
+#define MT_FCE_PARAMETERS              0x0804
+#define MT_FCE_CSO                     0x0808
+
+#define MT_FCE_L2_STUFF                        0x080c
+#define MT_FCE_L2_STUFF_HT_L2_EN       BIT(0)
+#define MT_FCE_L2_STUFF_QOS_L2_EN      BIT(1)
+#define MT_FCE_L2_STUFF_RX_STUFF_EN    BIT(2)
+#define MT_FCE_L2_STUFF_TX_STUFF_EN    BIT(3)
+#define MT_FCE_L2_STUFF_WR_MPDU_LEN_EN BIT(4)
+#define MT_FCE_L2_STUFF_MVINV_BSWAP    BIT(5)
+#define MT_FCE_L2_STUFF_TS_CMD_QSEL_EN GENMASK(15, 8)
+#define MT_FCE_L2_STUFF_TS_LEN_EN      GENMASK(23, 16)
+#define MT_FCE_L2_STUFF_OTHER_PORT     GENMASK(25, 24)
+
+#define MT_FCE_WLAN_FLOW_CONTROL1      0x0824
+
+#define MT_TX_CPU_FROM_FCE_BASE_PTR    0x09a0
+#define MT_TX_CPU_FROM_FCE_MAX_COUNT   0x09a4
+#define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX        0x09a8
+
+#define MT_FCE_PDMA_GLOBAL_CONF                0x09c4
+
+#define MT_PAUSE_ENABLE_CONTROL1       0x0a38
+
+#define MT_FCE_SKIP_FS                 0x0a6c
+
+#define MT_MAC_CSR0                    0x1000
+
+#define MT_MAC_SYS_CTRL                        0x1004
+#define MT_MAC_SYS_CTRL_RESET_CSR      BIT(0)
+#define MT_MAC_SYS_CTRL_RESET_BBP      BIT(1)
+#define MT_MAC_SYS_CTRL_ENABLE_TX      BIT(2)
+#define MT_MAC_SYS_CTRL_ENABLE_RX      BIT(3)
+
+#define MT_MAC_ADDR_DW0                        0x1008
+#define MT_MAC_ADDR_DW1                        0x100c
+#define MT_MAC_ADDR_DW1_U2ME_MASK      GENMASK(23, 16)
+
+#define MT_MAC_BSSID_DW0               0x1010
+#define MT_MAC_BSSID_DW1               0x1014
+#define MT_MAC_BSSID_DW1_ADDR          GENMASK(15, 0)
+#define MT_MAC_BSSID_DW1_MBSS_MODE     GENMASK(17, 16)
+#define MT_MAC_BSSID_DW1_MBEACON_N     GENMASK(20, 18)
+#define MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT        BIT(21)
+#define MT_MAC_BSSID_DW1_MBSS_MODE_B2  BIT(22)
+#define MT_MAC_BSSID_DW1_MBEACON_N_B3  BIT(23)
+#define MT_MAC_BSSID_DW1_MBSS_IDX_BYTE GENMASK(26, 24)
+
+#define MT_MAX_LEN_CFG                 0x1018
+#define MT_MAX_LEN_CFG_AMPDU           GENMASK(13, 12)
+
+#define MT_BBP_CSR_CFG                 0x101c
+#define MT_BBP_CSR_CFG_VAL             GENMASK(7, 0)
+#define MT_BBP_CSR_CFG_REG_NUM         GENMASK(15, 8)
+#define MT_BBP_CSR_CFG_READ            BIT(16)
+#define MT_BBP_CSR_CFG_BUSY            BIT(17)
+#define MT_BBP_CSR_CFG_PAR_DUR         BIT(18)
+#define MT_BBP_CSR_CFG_RW_MODE         BIT(19)
+
+#define MT_AMPDU_MAX_LEN_20M1S         0x1030
+#define MT_AMPDU_MAX_LEN_20M2S         0x1034
+#define MT_AMPDU_MAX_LEN_40M1S         0x1038
+#define MT_AMPDU_MAX_LEN_40M2S         0x103c
+#define MT_AMPDU_MAX_LEN               0x1040
+
+#define MT_WCID_DROP_BASE              0x106c
+#define MT_WCID_DROP(_n)               (MT_WCID_DROP_BASE + ((_n) >> 5) * 4)
+#define MT_WCID_DROP_MASK(_n)          BIT((_n) % 32)
+
+#define MT_BCN_BYPASS_MASK             0x108c
+
+#define MT_MAC_APC_BSSID_BASE          0x1090
+#define MT_MAC_APC_BSSID_L(_n)         (MT_MAC_APC_BSSID_BASE + ((_n) * 8))
+#define MT_MAC_APC_BSSID_H(_n)         (MT_MAC_APC_BSSID_BASE + ((_n) * 8 + 4))
+#define MT_MAC_APC_BSSID_H_ADDR                GENMASK(15, 0)
+#define MT_MAC_APC_BSSID0_H_EN         BIT(16)
+
+#define MT_XIFS_TIME_CFG               0x1100
+#define MT_XIFS_TIME_CFG_CCK_SIFS      GENMASK(7, 0)
+#define MT_XIFS_TIME_CFG_OFDM_SIFS     GENMASK(15, 8)
+#define MT_XIFS_TIME_CFG_OFDM_XIFS     GENMASK(19, 16)
+#define MT_XIFS_TIME_CFG_EIFS          GENMASK(28, 20)
+#define MT_XIFS_TIME_CFG_BB_RXEND_EN   BIT(29)
+
+#define MT_BKOFF_SLOT_CFG              0x1104
+#define MT_BKOFF_SLOT_CFG_SLOTTIME     GENMASK(7, 0)
+#define MT_BKOFF_SLOT_CFG_CC_DELAY     GENMASK(11, 8)
+
+#define MT_BEACON_TIME_CFG             0x1114
+#define MT_BEACON_TIME_CFG_INTVAL      GENMASK(15, 0)
+#define MT_BEACON_TIME_CFG_TIMER_EN    BIT(16)
+#define MT_BEACON_TIME_CFG_SYNC_MODE   GENMASK(18, 17)
+#define MT_BEACON_TIME_CFG_TBTT_EN     BIT(19)
+#define MT_BEACON_TIME_CFG_BEACON_TX   BIT(20)
+#define MT_BEACON_TIME_CFG_TSF_COMP    GENMASK(31, 24)
+
+#define MT_TBTT_SYNC_CFG               0x1118
+#define MT_TBTT_TIMER_CFG              0x1124
+
+#define MT_INT_TIMER_CFG               0x1128
+#define MT_INT_TIMER_CFG_PRE_TBTT      GENMASK(15, 0)
+#define MT_INT_TIMER_CFG_GP_TIMER      GENMASK(31, 16)
+
+#define MT_INT_TIMER_EN                        0x112c
+#define MT_INT_TIMER_EN_PRE_TBTT_EN    BIT(0)
+#define MT_INT_TIMER_EN_GP_TIMER_EN    BIT(1)
+
+#define MT_MAC_STATUS                  0x1200
+#define MT_MAC_STATUS_TX               BIT(0)
+#define MT_MAC_STATUS_RX               BIT(1)
+
+#define MT_PWR_PIN_CFG                 0x1204
+#define MT_AUX_CLK_CFG                 0x120c
+
+#define MT_BB_PA_MODE_CFG0             0x1214
+#define MT_BB_PA_MODE_CFG1             0x1218
+#define MT_RF_PA_MODE_CFG0             0x121c
+#define MT_RF_PA_MODE_CFG1             0x1220
+
+#define MT_RF_PA_MODE_ADJ0             0x1228
+#define MT_RF_PA_MODE_ADJ1             0x122c
+
+#define MT_DACCLK_EN_DLY_CFG           0x1264
+
+#define MT_EDCA_CFG_BASE               0x1300
+#define MT_EDCA_CFG_AC(_n)             (MT_EDCA_CFG_BASE + ((_n) << 2))
+#define MT_EDCA_CFG_TXOP               GENMASK(7, 0)
+#define MT_EDCA_CFG_AIFSN              GENMASK(11, 8)
+#define MT_EDCA_CFG_CWMIN              GENMASK(15, 12)
+#define MT_EDCA_CFG_CWMAX              GENMASK(19, 16)
+
+#define MT_TX_PWR_CFG_0                        0x1314
+#define MT_TX_PWR_CFG_1                        0x1318
+#define MT_TX_PWR_CFG_2                        0x131c
+#define MT_TX_PWR_CFG_3                        0x1320
+#define MT_TX_PWR_CFG_4                        0x1324
+
+#define MT_TX_BAND_CFG                 0x132c
+#define MT_TX_BAND_CFG_UPPER_40M       BIT(0)
+#define MT_TX_BAND_CFG_5G              BIT(1)
+#define MT_TX_BAND_CFG_2G              BIT(2)
+
+#define MT_HT_FBK_TO_LEGACY            0x1384
+#define MT_TX_MPDU_ADJ_INT             0x1388
+
+#define MT_TX_PWR_CFG_7                        0x13d4
+#define MT_TX_PWR_CFG_8                        0x13d8
+#define MT_TX_PWR_CFG_9                        0x13dc
+
+#define MT_TX_SW_CFG0                  0x1330
+#define MT_TX_SW_CFG1                  0x1334
+#define MT_TX_SW_CFG2                  0x1338
+
+#define MT_TXOP_CTRL_CFG               0x1340
+#define MT_TXOP_TRUN_EN                        GENMASK(5, 0)
+#define MT_TXOP_EXT_CCA_DLY            GENMASK(15, 8)
+#define MT_TXOP_CTRL
+
+#define MT_TX_RTS_CFG                  0x1344
+#define MT_TX_RTS_CFG_RETRY_LIMIT      GENMASK(7, 0)
+#define MT_TX_RTS_CFG_THRESH           GENMASK(23, 8)
+#define MT_TX_RTS_FALLBACK             BIT(24)
+
+#define MT_TX_TIMEOUT_CFG              0x1348
+#define MT_TX_RETRY_CFG                        0x134c
+#define MT_TX_LINK_CFG                 0x1350
+#define MT_HT_FBK_CFG0                 0x1354
+#define MT_HT_FBK_CFG1                 0x1358
+#define MT_LG_FBK_CFG0                 0x135c
+#define MT_LG_FBK_CFG1                 0x1360
+
+#define MT_CCK_PROT_CFG                        0x1364
+#define MT_OFDM_PROT_CFG               0x1368
+#define MT_MM20_PROT_CFG               0x136c
+#define MT_MM40_PROT_CFG               0x1370
+#define MT_GF20_PROT_CFG               0x1374
+#define MT_GF40_PROT_CFG               0x1378
+
+#define MT_PROT_RATE                   GENMASK(15, 0)
+#define MT_PROT_CTRL_RTS_CTS           BIT(16)
+#define MT_PROT_CTRL_CTS2SELF          BIT(17)
+#define MT_PROT_NAV_SHORT              BIT(18)
+#define MT_PROT_NAV_LONG               BIT(19)
+#define MT_PROT_TXOP_ALLOW_CCK         BIT(20)
+#define MT_PROT_TXOP_ALLOW_OFDM                BIT(21)
+#define MT_PROT_TXOP_ALLOW_MM20                BIT(22)
+#define MT_PROT_TXOP_ALLOW_MM40                BIT(23)
+#define MT_PROT_TXOP_ALLOW_GF20                BIT(24)
+#define MT_PROT_TXOP_ALLOW_GF40                BIT(25)
+#define MT_PROT_RTS_THR_EN             BIT(26)
+#define MT_PROT_RATE_CCK_11            0x0003
+#define MT_PROT_RATE_OFDM_6            0x4000
+#define MT_PROT_RATE_OFDM_24           0x4004
+#define MT_PROT_RATE_DUP_OFDM_24       0x4084
+#define MT_PROT_TXOP_ALLOW_ALL         GENMASK(25, 20)
+#define MT_PROT_TXOP_ALLOW_BW20                (MT_PROT_TXOP_ALLOW_ALL &       \
+                                        ~MT_PROT_TXOP_ALLOW_MM40 &     \
+                                        ~MT_PROT_TXOP_ALLOW_GF40)
+
+#define MT_EXP_ACK_TIME                        0x1380
+
+#define MT_TX_PWR_CFG_0_EXT            0x1390
+#define MT_TX_PWR_CFG_1_EXT            0x1394
+
+#define MT_TX_FBK_LIMIT                        0x1398
+#define MT_TX_FBK_LIMIT_MPDU_FBK       GENMASK(7, 0)
+#define MT_TX_FBK_LIMIT_AMPDU_FBK      GENMASK(15, 8)
+#define MT_TX_FBK_LIMIT_MPDU_UP_CLEAR  BIT(16)
+#define MT_TX_FBK_LIMIT_AMPDU_UP_CLEAR BIT(17)
+#define MT_TX_FBK_LIMIT_RATE_LUT       BIT(18)
+
+#define MT_TX0_RF_GAIN_CORR            0x13a0
+#define MT_TX1_RF_GAIN_CORR            0x13a4
+#define MT_TX0_RF_GAIN_ATTEN           0x13a8
+
+#define MT_TX_ALC_CFG_0                        0x13b0
+#define MT_TX_ALC_CFG_0_CH_INIT_0      GENMASK(5, 0)
+#define MT_TX_ALC_CFG_0_CH_INIT_1      GENMASK(13, 8)
+#define MT_TX_ALC_CFG_0_LIMIT_0                GENMASK(21, 16)
+#define MT_TX_ALC_CFG_0_LIMIT_1                GENMASK(29, 24)
+
+#define MT_TX_ALC_CFG_1                        0x13b4
+#define MT_TX_ALC_CFG_1_TEMP_COMP      GENMASK(5, 0)
+
+#define MT_TX_ALC_CFG_2                        0x13a8
+#define MT_TX_ALC_CFG_2_TEMP_COMP      GENMASK(5, 0)
+
+#define MT_TX0_BB_GAIN_ATTEN           0x13c0
+
+#define MT_TX_ALC_VGA3                 0x13c8
+
+#define MT_TX_PROT_CFG6                        0x13e0
+#define MT_TX_PROT_CFG7                        0x13e4
+#define MT_TX_PROT_CFG8                        0x13e8
+
+#define MT_PIFS_TX_CFG                 0x13ec
+
+#define MT_RX_FILTR_CFG                        0x1400
+
+#define MT_RX_FILTR_CFG_CRC_ERR                BIT(0)
+#define MT_RX_FILTR_CFG_PHY_ERR                BIT(1)
+#define MT_RX_FILTR_CFG_PROMISC                BIT(2)
+#define MT_RX_FILTR_CFG_OTHER_BSS      BIT(3)
+#define MT_RX_FILTR_CFG_VER_ERR                BIT(4)
+#define MT_RX_FILTR_CFG_MCAST          BIT(5)
+#define MT_RX_FILTR_CFG_BCAST          BIT(6)
+#define MT_RX_FILTR_CFG_DUP            BIT(7)
+#define MT_RX_FILTR_CFG_CFACK          BIT(8)
+#define MT_RX_FILTR_CFG_CFEND          BIT(9)
+#define MT_RX_FILTR_CFG_ACK            BIT(10)
+#define MT_RX_FILTR_CFG_CTS            BIT(11)
+#define MT_RX_FILTR_CFG_RTS            BIT(12)
+#define MT_RX_FILTR_CFG_PSPOLL         BIT(13)
+#define MT_RX_FILTR_CFG_BA             BIT(14)
+#define MT_RX_FILTR_CFG_BAR            BIT(15)
+#define MT_RX_FILTR_CFG_CTRL_RSV       BIT(16)
+
+#define MT_AUTO_RSP_CFG                        0x1404
+
+#define MT_AUTO_RSP_PREAMB_SHORT       BIT(4)
+
+#define MT_LEGACY_BASIC_RATE           0x1408
+#define MT_HT_BASIC_RATE               0x140c
+
+#define MT_RX_PARSER_CFG               0x1418
+#define MT_RX_PARSER_RX_SET_NAV_ALL    BIT(0)
+
+#define MT_EXT_CCA_CFG                 0x141c
+#define MT_EXT_CCA_CFG_CCA0            GENMASK(1, 0)
+#define MT_EXT_CCA_CFG_CCA1            GENMASK(3, 2)
+#define MT_EXT_CCA_CFG_CCA2            GENMASK(5, 4)
+#define MT_EXT_CCA_CFG_CCA3            GENMASK(7, 6)
+#define MT_EXT_CCA_CFG_CCA_MASK                GENMASK(11, 8)
+#define MT_EXT_CCA_CFG_ED_CCA_MASK     GENMASK(15, 12)
+
+#define MT_TX_SW_CFG3                  0x1478
+
+#define MT_PN_PAD_MODE                 0x150c
+
+#define MT_TXOP_HLDR_ET                        0x1608
+
+#define MT_PROT_AUTO_TX_CFG            0x1648
+
+#define MT_RX_STA_CNT0                 0x1700
+#define MT_RX_STA_CNT1                 0x1704
+#define MT_RX_STA_CNT2                 0x1708
+#define MT_TX_STA_CNT0                 0x170c
+#define MT_TX_STA_CNT1                 0x1710
+#define MT_TX_STA_CNT2                 0x1714
+
+/* Vendor driver defines content of the second word of STAT_FIFO as follows:
+ *     MT_TX_STAT_FIFO_RATE            GENMASK(26, 16)
+ *     MT_TX_STAT_FIFO_ETXBF           BIT(27)
+ *     MT_TX_STAT_FIFO_SND             BIT(28)
+ *     MT_TX_STAT_FIFO_ITXBF           BIT(29)
+ * However, tests show that b16-31 have the same layout as TXWI rate_ctl
+ * with rate set to rate at which frame was acked.
+ */
+#define MT_TX_STAT_FIFO                        0x1718
+#define MT_TX_STAT_FIFO_VALID          BIT(0)
+#define MT_TX_STAT_FIFO_PID_TYPE       GENMASK(4, 1)
+#define MT_TX_STAT_FIFO_SUCCESS                BIT(5)
+#define MT_TX_STAT_FIFO_AGGR           BIT(6)
+#define MT_TX_STAT_FIFO_ACKREQ         BIT(7)
+#define MT_TX_STAT_FIFO_WCID           GENMASK(15, 8)
+#define MT_TX_STAT_FIFO_RATE           GENMASK(31, 16)
+
+#define MT_TX_AGG_STAT                 0x171c
+
+#define MT_TX_AGG_CNT_BASE0            0x1720
+
+#define MT_MPDU_DENSITY_CNT            0x1740
+
+#define MT_TX_AGG_CNT_BASE1            0x174c
+
+#define MT_TX_AGG_CNT(_id)             ((_id) < 8 ?                    \
+                                        MT_TX_AGG_CNT_BASE0 + ((_id) << 2) : \
+                                        MT_TX_AGG_CNT_BASE1 + ((_id - 8) << 2))
+
+#define MT_TX_STAT_FIFO_EXT            0x1798
+#define MT_TX_STAT_FIFO_EXT_RETRY      GENMASK(7, 0)
+
+#define MT_BBP_CORE_BASE               0x2000
+#define MT_BBP_IBI_BASE                        0x2100
+#define MT_BBP_AGC_BASE                        0x2300
+#define MT_BBP_TXC_BASE                        0x2400
+#define MT_BBP_RXC_BASE                        0x2500
+#define MT_BBP_TXO_BASE                        0x2600
+#define MT_BBP_TXBE_BASE               0x2700
+#define MT_BBP_RXFE_BASE               0x2800
+#define MT_BBP_RXO_BASE                        0x2900
+#define MT_BBP_DFS_BASE                        0x2a00
+#define MT_BBP_TR_BASE                 0x2b00
+#define MT_BBP_CAL_BASE                        0x2c00
+#define MT_BBP_DSC_BASE                        0x2e00
+#define MT_BBP_PFMU_BASE               0x2f00
+
+#define MT_BBP(_type, _n)              (MT_BBP_##_type##_BASE + ((_n) << 2))
+
+#define MT_BBP_CORE_R1_BW              GENMASK(4, 3)
+
+#define MT_BBP_AGC_R0_CTRL_CHAN                GENMASK(9, 8)
+#define MT_BBP_AGC_R0_BW               GENMASK(14, 12)
+
+/* AGC, R4/R5 */
+#define MT_BBP_AGC_LNA_GAIN            GENMASK(21, 16)
+
+/* AGC, R8/R9 */
+#define MT_BBP_AGC_GAIN                        GENMASK(14, 8)
+
+#define MT_BBP_AGC20_RSSI0             GENMASK(7, 0)
+#define MT_BBP_AGC20_RSSI1             GENMASK(15, 8)
+
+#define MT_BBP_TXBE_R0_CTRL_CHAN       GENMASK(1, 0)
+
+#define MT_WCID_ADDR_BASE              0x1800
+#define MT_WCID_ADDR(_n)               (MT_WCID_ADDR_BASE + (_n) * 8)
+
+#define MT_SRAM_BASE                   0x4000
+
+#define MT_WCID_KEY_BASE               0x8000
+#define MT_WCID_KEY(_n)                        (MT_WCID_KEY_BASE + (_n) * 32)
+
+#define MT_WCID_IV_BASE                        0xa000
+#define MT_WCID_IV(_n)                 (MT_WCID_IV_BASE + (_n) * 8)
+
+#define MT_WCID_ATTR_BASE              0xa800
+#define MT_WCID_ATTR(_n)               (MT_WCID_ATTR_BASE + (_n) * 4)
+
+#define MT_WCID_ATTR_PAIRWISE          BIT(0)
+#define MT_WCID_ATTR_PKEY_MODE         GENMASK(3, 1)
+#define MT_WCID_ATTR_BSS_IDX           GENMASK(6, 4)
+#define MT_WCID_ATTR_RXWI_UDF          GENMASK(9, 7)
+#define MT_WCID_ATTR_PKEY_MODE_EXT     BIT(10)
+#define MT_WCID_ATTR_BSS_IDX_EXT       BIT(11)
+#define MT_WCID_ATTR_WAPI_MCBC         BIT(15)
+#define MT_WCID_ATTR_WAPI_KEYID                GENMASK(31, 24)
+
+#define MT_SKEY_BASE_0                 0xac00
+#define MT_SKEY_BASE_1                 0xb400
+#define MT_SKEY_0(_bss, _idx)          \
+       (MT_SKEY_BASE_0 + (4 * (_bss) + _idx) * 32)
+#define MT_SKEY_1(_bss, _idx)          \
+       (MT_SKEY_BASE_1 + (4 * ((_bss) & 7) + _idx) * 32)
+#define MT_SKEY(_bss, _idx)            \
+       ((_bss & 8) ? MT_SKEY_1(_bss, _idx) : MT_SKEY_0(_bss, _idx))
+
+#define MT_SKEY_MODE_BASE_0            0xb000
+#define MT_SKEY_MODE_BASE_1            0xb3f0
+#define MT_SKEY_MODE_0(_bss)           \
+       (MT_SKEY_MODE_BASE_0 + ((_bss / 2) << 2))
+#define MT_SKEY_MODE_1(_bss)           \
+       (MT_SKEY_MODE_BASE_1 + ((((_bss) & 7) / 2) << 2))
+#define MT_SKEY_MODE(_bss)             \
+       ((_bss & 8) ? MT_SKEY_MODE_1(_bss) : MT_SKEY_MODE_0(_bss))
+#define MT_SKEY_MODE_MASK              GENMASK(3, 0)
+#define MT_SKEY_MODE_SHIFT(_bss, _idx) (4 * ((_idx) + 4 * (_bss & 1)))
+
+#define MT_BEACON_BASE                 0xc000
+
+#define MT_TEMP_SENSOR                 0x1d000
+#define MT_TEMP_SENSOR_VAL             GENMASK(6, 0)
+
+enum mt76_cipher_type {
+       MT_CIPHER_NONE,
+       MT_CIPHER_WEP40,
+       MT_CIPHER_WEP104,
+       MT_CIPHER_TKIP,
+       MT_CIPHER_AES_CCMP,
+       MT_CIPHER_CKIP40,
+       MT_CIPHER_CKIP104,
+       MT_CIPHER_CKIP128,
+       MT_CIPHER_WAPI,
+};
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.c b/drivers/net/wireless/mediatek/mt7601u/trace.c
new file mode 100644 (file)
index 0000000..8abdd3c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.h b/drivers/net/wireless/mediatek/mt7601u/trace.h
new file mode 100644 (file)
index 0000000..2898973
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#if !defined(__MT7601U_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __MT7601U_TRACE_H
+
+#include <linux/tracepoint.h>
+#include "mt7601u.h"
+#include "mac.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mt7601u
+
+#define MAXNAME                32
+#define DEV_ENTRY      __array(char, wiphy_name, 32)
+#define DEV_ASSIGN     strlcpy(__entry->wiphy_name,                    \
+                               wiphy_name(dev->hw->wiphy), MAXNAME)
+#define DEV_PR_FMT     "%s "
+#define DEV_PR_ARG     __entry->wiphy_name
+
+#define REG_ENTRY      __field(u32, reg) __field(u32, val)
+#define REG_ASSIGN     __entry->reg = reg; __entry->val = val
+#define REG_PR_FMT     "%04x=%08x"
+#define REG_PR_ARG     __entry->reg, __entry->val
+
+DECLARE_EVENT_CLASS(dev_reg_evt,
+       TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
+       TP_ARGS(dev, reg, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               REG_ENTRY
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               REG_ASSIGN;
+       ),
+       TP_printk(
+               DEV_PR_FMT REG_PR_FMT,
+               DEV_PR_ARG, REG_PR_ARG
+       )
+);
+
+DEFINE_EVENT(dev_reg_evt, reg_read,
+       TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
+       TP_ARGS(dev, reg, val)
+);
+
+DEFINE_EVENT(dev_reg_evt, reg_write,
+       TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
+       TP_ARGS(dev, reg, val)
+);
+
+TRACE_EVENT(mt_submit_urb,
+       TP_PROTO(struct mt7601u_dev *dev, struct urb *u),
+       TP_ARGS(dev, u),
+       TP_STRUCT__entry(
+               DEV_ENTRY __field(unsigned, pipe) __field(u32, len)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->pipe = u->pipe;
+               __entry->len = u->transfer_buffer_length;
+       ),
+       TP_printk(DEV_PR_FMT "p:%08x len:%u",
+                 DEV_PR_ARG, __entry->pipe, __entry->len)
+);
+
+#define trace_mt_submit_urb_sync(__dev, __pipe, __len) ({      \
+       struct urb u;                                   \
+       u.pipe = __pipe;                                \
+       u.transfer_buffer_length = __len;               \
+       trace_mt_submit_urb(__dev, &u);                 \
+})
+
+TRACE_EVENT(mt_mcu_msg_send,
+       TP_PROTO(struct mt7601u_dev *dev,
+                struct sk_buff *skb, u32 csum, bool resp),
+       TP_ARGS(dev, skb, csum, resp),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, info)
+               __field(u32, csum)
+               __field(bool, resp)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->info = *(u32 *)skb->data;
+               __entry->csum = csum;
+               __entry->resp = resp;
+       ),
+       TP_printk(DEV_PR_FMT "i:%08x c:%08x r:%d",
+                 DEV_PR_ARG, __entry->info, __entry->csum, __entry->resp)
+);
+
+TRACE_EVENT(mt_vend_req,
+       TP_PROTO(struct mt7601u_dev *dev, unsigned pipe, u8 req, u8 req_type,
+                u16 val, u16 offset, void *buf, size_t buflen, int ret),
+       TP_ARGS(dev, pipe, req, req_type, val, offset, buf, buflen, ret),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(unsigned, pipe) __field(u8, req) __field(u8, req_type)
+               __field(u16, val) __field(u16, offset) __field(void*, buf)
+               __field(int, buflen) __field(int, ret)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->pipe = pipe;
+               __entry->req = req;
+               __entry->req_type = req_type;
+               __entry->val = val;
+               __entry->offset = offset;
+               __entry->buf = buf;
+               __entry->buflen = buflen;
+               __entry->ret = ret;
+       ),
+       TP_printk(DEV_PR_FMT
+                 "%d p:%08x req:%02hhx %02hhx val:%04hx %04hx buf:%d %d",
+                 DEV_PR_ARG, __entry->ret, __entry->pipe, __entry->req,
+                 __entry->req_type, __entry->val, __entry->offset,
+                 !!__entry->buf, __entry->buflen)
+);
+
+TRACE_EVENT(ee_read,
+       TP_PROTO(struct mt7601u_dev *dev, int offset, u16 val),
+       TP_ARGS(dev, offset, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(int, o) __field(u16, v)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->o = offset;
+               __entry->v = val;
+       ),
+       TP_printk(DEV_PR_FMT "%04x=%04x", DEV_PR_ARG, __entry->o, __entry->v)
+);
+
+DECLARE_EVENT_CLASS(dev_rf_reg_evt,
+       TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
+       TP_ARGS(dev, bank, reg, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, bank)
+               __field(u8, reg)
+               __field(u8, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               REG_ASSIGN;
+               __entry->bank = bank;
+       ),
+       TP_printk(
+               DEV_PR_FMT "%02hhx:%02hhx=%02hhx",
+               DEV_PR_ARG, __entry->bank, __entry->reg, __entry->val
+       )
+);
+
+DEFINE_EVENT(dev_rf_reg_evt, rf_read,
+       TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
+       TP_ARGS(dev, bank, reg, val)
+);
+
+DEFINE_EVENT(dev_rf_reg_evt, rf_write,
+       TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
+       TP_ARGS(dev, bank, reg, val)
+);
+
+DECLARE_EVENT_CLASS(dev_bbp_reg_evt,
+       TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
+       TP_ARGS(dev, reg, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, reg)
+               __field(u8, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               REG_ASSIGN;
+       ),
+       TP_printk(
+               DEV_PR_FMT "%02hhx=%02hhx",
+               DEV_PR_ARG, __entry->reg, __entry->val
+       )
+);
+
+DEFINE_EVENT(dev_bbp_reg_evt, bbp_read,
+       TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
+       TP_ARGS(dev, reg, val)
+);
+
+DEFINE_EVENT(dev_bbp_reg_evt, bbp_write,
+       TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
+       TP_ARGS(dev, reg, val)
+);
+
+DECLARE_EVENT_CLASS(dev_simple_evt,
+       TP_PROTO(struct mt7601u_dev *dev, u8 val),
+       TP_ARGS(dev, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->val = val;
+       ),
+       TP_printk(
+               DEV_PR_FMT "%02hhx", DEV_PR_ARG, __entry->val
+       )
+);
+
+DEFINE_EVENT(dev_simple_evt, temp_mode,
+       TP_PROTO(struct mt7601u_dev *dev, u8 val),
+       TP_ARGS(dev, val)
+);
+
+DEFINE_EVENT(dev_simple_evt, read_temp,
+       TP_PROTO(struct mt7601u_dev *dev, u8 val),
+       TP_ARGS(dev, val)
+);
+
+DEFINE_EVENT(dev_simple_evt, freq_cal_adjust,
+       TP_PROTO(struct mt7601u_dev *dev, u8 val),
+       TP_ARGS(dev, val)
+);
+
+TRACE_EVENT(freq_cal_offset,
+       TP_PROTO(struct mt7601u_dev *dev, u8 phy_mode, s8 freq_off),
+       TP_ARGS(dev, phy_mode, freq_off),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, phy_mode)
+               __field(s8, freq_off)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->phy_mode = phy_mode;
+               __entry->freq_off = freq_off;
+       ),
+       TP_printk(DEV_PR_FMT "phy:%02hhx off:%02hhx",
+                 DEV_PR_ARG, __entry->phy_mode, __entry->freq_off)
+);
+
+TRACE_EVENT(mt_rx,
+       TP_PROTO(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, u32 f),
+       TP_ARGS(dev, rxwi, f),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field_struct(struct mt7601u_rxwi, rxwi)
+               __field(u32, fce_info)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->rxwi = *rxwi;
+               __entry->fce_info = f;
+       ),
+       TP_printk(DEV_PR_FMT "rxi:%08x ctl:%08x frag_sn:%04hx rate:%04hx "
+                 "uknw:%02hhx z:%02hhx%02hhx%02hhx snr:%02hhx "
+                 "ant:%02hhx gain:%02hhx freq_o:%02hhx "
+                 "r:%08x ea:%08x fce:%08x", DEV_PR_ARG,
+                 le32_to_cpu(__entry->rxwi.rxinfo),
+                 le32_to_cpu(__entry->rxwi.ctl),
+                 le16_to_cpu(__entry->rxwi.frag_sn),
+                 le16_to_cpu(__entry->rxwi.rate),
+                 __entry->rxwi.unknown,
+                 __entry->rxwi.zero[0], __entry->rxwi.zero[1],
+                 __entry->rxwi.zero[2],
+                 __entry->rxwi.snr, __entry->rxwi.ant,
+                 __entry->rxwi.gain, __entry->rxwi.freq_off,
+                 __entry->rxwi.resv2, __entry->rxwi.expert_ant,
+                 __entry->fce_info)
+);
+
+TRACE_EVENT(mt_tx,
+       TP_PROTO(struct mt7601u_dev *dev, struct sk_buff *skb,
+                struct mt76_sta *sta, struct mt76_txwi *h),
+       TP_ARGS(dev, skb, sta, h),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field_struct(struct mt76_txwi, h)
+               __field(struct sk_buff *, skb)
+               __field(struct mt76_sta *, sta)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->h = *h;
+               __entry->skb = skb;
+               __entry->sta = sta;
+       ),
+       TP_printk(DEV_PR_FMT "skb:%p sta:%p  flg:%04hx rate_ctl:%04hx "
+                 "ack:%02hhx wcid:%02hhx len_ctl:%05hx", DEV_PR_ARG,
+                 __entry->skb, __entry->sta,
+                 le16_to_cpu(__entry->h.flags),
+                 le16_to_cpu(__entry->h.rate_ctl),
+                 __entry->h.ack_ctl, __entry->h.wcid,
+                 le16_to_cpu(__entry->h.len_ctl))
+);
+
+TRACE_EVENT(mt_tx_dma_done,
+       TP_PROTO(struct mt7601u_dev *dev, struct sk_buff *skb),
+       TP_ARGS(dev, skb),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(struct sk_buff *, skb)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->skb = skb;
+       ),
+       TP_printk(DEV_PR_FMT "%p", DEV_PR_ARG, __entry->skb)
+);
+
+TRACE_EVENT(mt_tx_status_cleaned,
+       TP_PROTO(struct mt7601u_dev *dev, int cleaned),
+       TP_ARGS(dev, cleaned),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(int, cleaned)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->cleaned = cleaned;
+       ),
+       TP_printk(DEV_PR_FMT "%d", DEV_PR_ARG, __entry->cleaned)
+);
+
+TRACE_EVENT(mt_tx_status,
+       TP_PROTO(struct mt7601u_dev *dev, u32 stat1, u32 stat2),
+       TP_ARGS(dev, stat1, stat2),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, stat1)     __field(u32, stat2)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->stat1 = stat1;
+               __entry->stat2 = stat2;
+       ),
+       TP_printk(DEV_PR_FMT "%08x %08x",
+                 DEV_PR_ARG, __entry->stat1, __entry->stat2)
+);
+
+TRACE_EVENT(mt_rx_dma_aggr,
+       TP_PROTO(struct mt7601u_dev *dev, int cnt, bool paged),
+       TP_ARGS(dev, cnt, paged),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, cnt)
+               __field(bool, paged)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->cnt = cnt;
+               __entry->paged = paged;
+       ),
+       TP_printk(DEV_PR_FMT "cnt:%d paged:%d",
+                 DEV_PR_ARG, __entry->cnt, __entry->paged)
+);
+
+DEFINE_EVENT(dev_simple_evt, set_key,
+       TP_PROTO(struct mt7601u_dev *dev, u8 val),
+       TP_ARGS(dev, val)
+);
+
+TRACE_EVENT(set_shared_key,
+       TP_PROTO(struct mt7601u_dev *dev, u8 vid, u8 key),
+       TP_ARGS(dev, vid, key),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u8, vid)
+               __field(u8, key)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->vid = vid;
+               __entry->key = key;
+       ),
+       TP_printk(DEV_PR_FMT "phy:%02hhx off:%02hhx",
+                 DEV_PR_ARG, __entry->vid, __entry->key)
+);
+
+#endif
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/mediatek/mt7601u/tx.c b/drivers/net/wireless/mediatek/mt7601u/tx.c
new file mode 100644 (file)
index 0000000..0be2080
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+#include "trace.h"
+
+enum mt76_txq_id {
+       MT_TXQ_VO = IEEE80211_AC_VO,
+       MT_TXQ_VI = IEEE80211_AC_VI,
+       MT_TXQ_BE = IEEE80211_AC_BE,
+       MT_TXQ_BK = IEEE80211_AC_BK,
+       MT_TXQ_PSD,
+       MT_TXQ_MCU,
+       __MT_TXQ_MAX
+};
+
+/* Hardware uses mirrored order of queues with Q0 having the highest priority */
+static u8 q2hwq(u8 q)
+{
+       return q ^ 0x3;
+}
+
+/* Take mac80211 Q id from the skb and translate it to hardware Q id */
+static u8 skb2q(struct sk_buff *skb)
+{
+       int qid = skb_get_queue_mapping(skb);
+
+       if (WARN_ON(qid >= MT_TXQ_PSD)) {
+               qid = MT_TXQ_BE;
+               skb_set_queue_mapping(skb, qid);
+       }
+
+       return q2hwq(qid);
+}
+
+/* Note: TX retry reporting is a bit broken.
+ *      Retries are reported only once per AMPDU and often come a frame early
+ *      i.e. they are reported in the last status preceding the AMPDU. Apart
+ *      from the fact that it's hard to know the length of the AMPDU (which is
+ *      required to know to how many consecutive frames retries should be
+ *      applied), if status comes early on full FIFO it gets lost and retries
+ *      of the whole AMPDU become invisible.
+ *      As a work-around encode the desired rate in PKT_ID of TX descriptor
+ *      and based on that guess the retries (every rate is tried once).
+ *      Only downside here is that for MCS0 we have to rely solely on
+ *      transmission failures as no retries can ever be reported.
+ *      Not having to read EXT_FIFO has a nice effect of doubling the number
+ *      of reports which can be fetched.
+ *      Also the vendor driver never uses the EXT_FIFO register so it may be
+ *      undertested.
+ */
+static u8 mt7601u_tx_pktid_enc(struct mt7601u_dev *dev, u8 rate, bool is_probe)
+{
+       u8 encoded = (rate + 1) + is_probe *  8;
+
+       /* Because PKT_ID 0 disables status reporting only 15 values are
+        * available but 16 are needed (8 MCS * 2 for encoding is_probe)
+        * - we need to cram together two rates. MCS0 and MCS7 with is_probe
+        * share PKT_ID 9.
+        */
+       if (is_probe && rate == 7)
+               return encoded - 7;
+
+       return encoded;
+}
+
+static void
+mt7601u_tx_pktid_dec(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
+{
+       u8 req_rate = stat->pktid;
+       u8 eff_rate = stat->rate & 0x7;
+
+       req_rate -= 1;
+
+       if (req_rate > 7) {
+               stat->is_probe = true;
+               req_rate -= 8;
+
+               /* Decide between MCS0 and MCS7 which share pktid 9 */
+               if (!req_rate && eff_rate)
+                       req_rate = 7;
+       }
+
+       stat->retry = req_rate - eff_rate;
+}
+
+static void mt7601u_tx_skb_remove_dma_overhead(struct sk_buff *skb,
+                                              struct ieee80211_tx_info *info)
+{
+       int pkt_len = (unsigned long)info->status.status_driver_data[0];
+
+       skb_pull(skb, sizeof(struct mt76_txwi) + 4);
+       if (ieee80211_get_hdrlen_from_skb(skb) % 4)
+               mt76_remove_hdr_pad(skb);
+
+       skb_trim(skb, pkt_len);
+}
+
+void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       mt7601u_tx_skb_remove_dma_overhead(skb, info);
+
+       ieee80211_tx_info_clear_status(info);
+       info->status.rates[0].idx = -1;
+       info->flags |= IEEE80211_TX_STAT_ACK;
+       ieee80211_tx_status(dev->hw, skb);
+}
+
+static int mt7601u_skb_rooms(struct mt7601u_dev *dev, struct sk_buff *skb)
+{
+       int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+       u32 need_head;
+
+       need_head = sizeof(struct mt76_txwi) + 4;
+       if (hdr_len % 4)
+               need_head += 2;
+
+       return skb_cow(skb, need_head);
+}
+
+static struct mt76_txwi *
+mt7601u_push_txwi(struct mt7601u_dev *dev, struct sk_buff *skb,
+                 struct ieee80211_sta *sta, struct mt76_wcid *wcid,
+                 int pkt_len)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *rate = &info->control.rates[0];
+       struct mt76_txwi *txwi;
+       unsigned long flags;
+       bool is_probe;
+       u32 pkt_id;
+       u16 rate_ctl;
+       u8 nss;
+
+       txwi = (struct mt76_txwi *)skb_push(skb, sizeof(struct mt76_txwi));
+       memset(txwi, 0, sizeof(*txwi));
+
+       if (!wcid->tx_rate_set)
+               ieee80211_get_tx_rates(info->control.vif, sta, skb,
+                                      info->control.rates, 1);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       if (rate->idx < 0 || !rate->count)
+               rate_ctl = wcid->tx_rate;
+       else
+               rate_ctl = mt76_mac_tx_rate_val(dev, rate, &nss);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       txwi->rate_ctl = cpu_to_le16(rate_ctl);
+
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+               txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ;
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+               txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ;
+
+       if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) {
+               u8 ba_size = IEEE80211_MIN_AMPDU_BUF;
+
+               ba_size <<= sta->ht_cap.ampdu_factor;
+               ba_size = min_t(int, 63, ba_size);
+               if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+                       ba_size = 0;
+               txwi->ack_ctl |= MT76_SET(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size);
+
+               txwi->flags = cpu_to_le16(MT_TXWI_FLAGS_AMPDU |
+                                         MT76_SET(MT_TXWI_FLAGS_MPDU_DENSITY,
+                                                  sta->ht_cap.ampdu_density));
+               if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+                       txwi->flags = 0;
+       }
+
+       txwi->wcid = wcid->idx;
+
+       is_probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+       pkt_id = mt7601u_tx_pktid_enc(dev, rate_ctl & 0x7, is_probe);
+       pkt_len |= MT76_SET(MT_TXWI_LEN_PKTID, pkt_id);
+       txwi->len_ctl = cpu_to_le16(pkt_len);
+
+       return txwi;
+}
+
+void mt7601u_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
+               struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct mt7601u_dev *dev = hw->priv;
+       struct ieee80211_vif *vif = info->control.vif;
+       struct ieee80211_sta *sta = control->sta;
+       struct mt76_sta *msta = NULL;
+       struct mt76_wcid *wcid = dev->mon_wcid;
+       struct mt76_txwi *txwi;
+       int pkt_len = skb->len;
+       int hw_q = skb2q(skb);
+
+       BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
+       info->status.status_driver_data[0] = (void *)(unsigned long)pkt_len;
+
+       if (mt7601u_skb_rooms(dev, skb) || mt76_insert_hdr_pad(skb)) {
+               ieee80211_free_txskb(dev->hw, skb);
+               return;
+       }
+
+       if (sta) {
+               msta = (struct mt76_sta *) sta->drv_priv;
+               wcid = &msta->wcid;
+       } else if (vif) {
+               struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
+
+               wcid = &mvif->group_wcid;
+       }
+
+       txwi = mt7601u_push_txwi(dev, skb, sta, wcid, pkt_len);
+
+       if (mt7601u_dma_enqueue_tx(dev, skb, wcid, hw_q))
+               return;
+
+       trace_mt_tx(dev, skb, msta, txwi);
+}
+
+void mt7601u_tx_stat(struct work_struct *work)
+{
+       struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
+                                              stat_work.work);
+       struct mt76_tx_status stat;
+       unsigned long flags;
+       int cleaned = 0;
+
+       while (!test_bit(MT7601U_STATE_REMOVED, &dev->state)) {
+               stat = mt7601u_mac_fetch_tx_status(dev);
+               if (!stat.valid)
+                       break;
+
+               mt7601u_tx_pktid_dec(dev, &stat);
+               mt76_send_tx_status(dev, &stat);
+
+               cleaned++;
+       }
+       trace_mt_tx_status_cleaned(dev, cleaned);
+
+       spin_lock_irqsave(&dev->tx_lock, flags);
+       if (cleaned)
+               queue_delayed_work(dev->stat_wq, &dev->stat_work,
+                                  msecs_to_jiffies(10));
+       else if (test_and_clear_bit(MT7601U_STATE_MORE_STATS, &dev->state))
+               queue_delayed_work(dev->stat_wq, &dev->stat_work,
+                                  msecs_to_jiffies(20));
+       else
+               clear_bit(MT7601U_STATE_READING_STATS, &dev->state);
+       spin_unlock_irqrestore(&dev->tx_lock, flags);
+}
+
+int mt7601u_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                   u16 queue, const struct ieee80211_tx_queue_params *params)
+{
+       struct mt7601u_dev *dev = hw->priv;
+       u8 cw_min = 5, cw_max = 10, hw_q = q2hwq(queue);
+       u32 val;
+
+       /* TODO: should we do funny things with the parameters?
+        *       See what mt7601u_set_default_edca() used to do in init.c.
+        */
+
+       if (params->cw_min)
+               cw_min = fls(params->cw_min);
+       if (params->cw_max)
+               cw_max = fls(params->cw_max);
+
+       WARN_ON(params->txop > 0xff);
+       WARN_ON(params->aifs > 0xf);
+       WARN_ON(cw_min > 0xf);
+       WARN_ON(cw_max > 0xf);
+
+       val = MT76_SET(MT_EDCA_CFG_AIFSN, params->aifs) |
+             MT76_SET(MT_EDCA_CFG_CWMIN, cw_min) |
+             MT76_SET(MT_EDCA_CFG_CWMAX, cw_max);
+       /* TODO: based on user-controlled EnableTxBurst var vendor drv sets
+        *       a really long txop on AC0 (see connect.c:2009) but only on
+        *       connect? When not connected should be 0.
+        */
+       if (!hw_q)
+               val |= 0x60;
+       else
+               val |= MT76_SET(MT_EDCA_CFG_TXOP, params->txop);
+       mt76_wr(dev, MT_EDCA_CFG_AC(hw_q), val);
+
+       val = mt76_rr(dev, MT_WMM_TXOP(hw_q));
+       val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(hw_q));
+       val |= params->txop << MT_WMM_TXOP_SHIFT(hw_q);
+       mt76_wr(dev, MT_WMM_TXOP(hw_q), val);
+
+       val = mt76_rr(dev, MT_WMM_AIFSN);
+       val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(hw_q));
+       val |= params->aifs << MT_WMM_AIFSN_SHIFT(hw_q);
+       mt76_wr(dev, MT_WMM_AIFSN, val);
+
+       val = mt76_rr(dev, MT_WMM_CWMIN);
+       val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(hw_q));
+       val |= cw_min << MT_WMM_CWMIN_SHIFT(hw_q);
+       mt76_wr(dev, MT_WMM_CWMIN, val);
+
+       val = mt76_rr(dev, MT_WMM_CWMAX);
+       val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(hw_q));
+       val |= cw_max << MT_WMM_CWMAX_SHIFT(hw_q);
+       mt76_wr(dev, MT_WMM_CWMAX, val);
+
+       return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c
new file mode 100644 (file)
index 0000000..99e2b39
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "mt7601u.h"
+#include "usb.h"
+#include "trace.h"
+
+static struct usb_device_id mt7601u_device_table[] = {
+       { USB_DEVICE(0x0b05, 0x17d3) },
+       { USB_DEVICE(0x0e8d, 0x760a) },
+       { USB_DEVICE(0x0e8d, 0x760b) },
+       { USB_DEVICE(0x13d3, 0x3431) },
+       { USB_DEVICE(0x13d3, 0x3434) },
+       { USB_DEVICE(0x148f, 0x7601) },
+       { USB_DEVICE(0x148f, 0x760a) },
+       { USB_DEVICE(0x148f, 0x760b) },
+       { USB_DEVICE(0x148f, 0x760c) },
+       { USB_DEVICE(0x148f, 0x760d) },
+       { USB_DEVICE(0x2001, 0x3d04) },
+       { USB_DEVICE(0x2717, 0x4106) },
+       { USB_DEVICE(0x2955, 0x0001) },
+       { USB_DEVICE(0x2955, 0x1001) },
+       { USB_DEVICE(0x2a5f, 0x1000) },
+       { USB_DEVICE(0x7392, 0x7710) },
+       { 0, }
+};
+
+bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
+                          struct mt7601u_dma_buf *buf)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+
+       buf->len = len;
+       buf->urb = usb_alloc_urb(0, GFP_KERNEL);
+       buf->buf = usb_alloc_coherent(usb_dev, buf->len, GFP_KERNEL, &buf->dma);
+
+       return !buf->urb || !buf->buf;
+}
+
+void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+
+       usb_free_coherent(usb_dev, buf->len, buf->buf, buf->dma);
+       usb_free_urb(buf->urb);
+}
+
+int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
+                          struct mt7601u_dma_buf *buf, gfp_t gfp,
+                          usb_complete_t complete_fn, void *context)
+{
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+       unsigned pipe;
+       int ret;
+
+       if (dir == USB_DIR_IN)
+               pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[ep_idx]);
+       else
+               pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep_idx]);
+
+       usb_fill_bulk_urb(buf->urb, usb_dev, pipe, buf->buf, buf->len,
+                         complete_fn, context);
+       buf->urb->transfer_dma = buf->dma;
+       buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       trace_mt_submit_urb(dev, buf->urb);
+       ret = usb_submit_urb(buf->urb, gfp);
+       if (ret)
+               dev_err(dev->dev, "Error: submit URB dir:%d ep:%d failed:%d\n",
+                       dir, ep_idx, ret);
+       return ret;
+}
+
+void mt7601u_complete_urb(struct urb *urb)
+{
+       struct completion *cmpl = urb->context;
+
+       complete(cmpl);
+}
+
+static int
+__mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
+                        const u8 direction, const u16 val, const u16 offset,
+                        void *buf, const size_t buflen)
+{
+       int i, ret;
+       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
+       const u8 req_type = direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       const unsigned int pipe = (direction == USB_DIR_IN) ?
+               usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
+
+       for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) {
+               ret = usb_control_msg(usb_dev, pipe, req, req_type,
+                                     val, offset, buf, buflen,
+                                     MT_VEND_REQ_TOUT_MS);
+               trace_mt_vend_req(dev, pipe, req, req_type, val, offset,
+                                 buf, buflen, ret);
+
+               if (ret >= 0 || ret == -ENODEV)
+                       return ret;
+
+               msleep(5);
+       }
+
+       dev_err(dev->dev, "Vendor request req:%02x off:%04x failed:%d\n",
+               req, offset, ret);
+
+       return ret;
+}
+
+int
+mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
+                      const u8 direction, const u16 val, const u16 offset,
+                      void *buf, const size_t buflen)
+{
+       int ret;
+
+       mutex_lock(&dev->vendor_req_mutex);
+
+       ret = __mt7601u_vendor_request(dev, req, direction, val, offset,
+                                      buf, buflen);
+       if (ret == -ENODEV)
+               set_bit(MT7601U_STATE_REMOVED, &dev->state);
+
+       mutex_unlock(&dev->vendor_req_mutex);
+
+       return ret;
+}
+
+void mt7601u_vendor_reset(struct mt7601u_dev *dev)
+{
+       mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
+                              MT_VEND_DEV_MODE_RESET, 0, NULL, 0);
+}
+
+u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
+{
+       int ret;
+       __le32 reg;
+       u32 val;
+
+       WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
+
+       ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
+                                    0, offset, &reg, sizeof(reg));
+       val = le32_to_cpu(reg);
+       if (ret > 0 && ret != sizeof(reg)) {
+               dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
+                       ret, offset);
+               val = ~0;
+       }
+
+       trace_reg_read(dev, offset, val);
+       return val;
+}
+
+int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
+                            const u16 offset, const u32 val)
+{
+       int ret;
+
+       ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
+                                    val & 0xffff, offset, NULL, 0);
+       if (ret)
+               return ret;
+       return mt7601u_vendor_request(dev, req, USB_DIR_OUT,
+                                     val >> 16, offset + 2, NULL, 0);
+}
+
+void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
+{
+       WARN_ONCE(offset > USHRT_MAX, "write high off:%08x", offset);
+
+       mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
+       trace_reg_write(dev, offset, val);
+}
+
+u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
+{
+       val |= mt7601u_rr(dev, offset) & ~mask;
+       mt7601u_wr(dev, offset, val);
+       return val;
+}
+
+u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
+{
+       u32 reg = mt7601u_rr(dev, offset);
+
+       val |= reg & ~mask;
+       if (reg != val)
+               mt7601u_wr(dev, offset, val);
+       return val;
+}
+
+void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
+                    const void *data, int len)
+{
+       WARN_ONCE(offset & 3, "unaligned write copy off:%08x", offset);
+       WARN_ONCE(len & 3, "short write copy off:%08x", offset);
+
+       mt7601u_burst_write_regs(dev, offset, data, len / 4);
+}
+
+void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr)
+{
+       mt7601u_wr(dev, offset, get_unaligned_le32(addr));
+       mt7601u_wr(dev, offset + 4, addr[4] | addr[5] << 8);
+}
+
+static int mt7601u_assign_pipes(struct usb_interface *usb_intf,
+                               struct mt7601u_dev *dev)
+{
+       struct usb_endpoint_descriptor *ep_desc;
+       struct usb_host_interface *intf_desc = usb_intf->cur_altsetting;
+       unsigned i, ep_i = 0, ep_o = 0;
+
+       BUILD_BUG_ON(sizeof(dev->in_eps) < __MT_EP_IN_MAX);
+       BUILD_BUG_ON(sizeof(dev->out_eps) < __MT_EP_OUT_MAX);
+
+       for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+               ep_desc = &intf_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_bulk_in(ep_desc) &&
+                   ep_i++ < __MT_EP_IN_MAX) {
+                       dev->in_eps[ep_i - 1] = usb_endpoint_num(ep_desc);
+                       dev->in_max_packet = usb_endpoint_maxp(ep_desc);
+                       /* Note: this is ignored by usb sub-system but vendor
+                        *       code does it. We can drop this at some point.
+                        */
+                       dev->in_eps[ep_i - 1] |= USB_DIR_IN;
+               } else if (usb_endpoint_is_bulk_out(ep_desc) &&
+                          ep_o++ < __MT_EP_OUT_MAX) {
+                       dev->out_eps[ep_o - 1] = usb_endpoint_num(ep_desc);
+                       dev->out_max_packet = usb_endpoint_maxp(ep_desc);
+               }
+       }
+
+       if (ep_i != __MT_EP_IN_MAX || ep_o != __MT_EP_OUT_MAX) {
+               dev_err(dev->dev, "Error: wrong pipe number in:%d out:%d\n",
+                       ep_i, ep_o);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mt7601u_probe(struct usb_interface *usb_intf,
+                        const struct usb_device_id *id)
+{
+       struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
+       struct mt7601u_dev *dev;
+       u32 asic_rev, mac_rev;
+       int ret;
+
+       dev = mt7601u_alloc_device(&usb_intf->dev);
+       if (!dev)
+               return -ENOMEM;
+
+       usb_dev = usb_get_dev(usb_dev);
+       usb_reset_device(usb_dev);
+
+       usb_set_intfdata(usb_intf, dev);
+
+       ret = mt7601u_assign_pipes(usb_intf, dev);
+       if (ret)
+               goto err;
+       ret = mt7601u_wait_asic_ready(dev);
+       if (ret)
+               goto err;
+
+       asic_rev = mt7601u_rr(dev, MT_ASIC_VERSION);
+       mac_rev = mt7601u_rr(dev, MT_MAC_CSR0);
+       dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n",
+                asic_rev, mac_rev);
+
+       /* Note: vendor driver skips this check for MT7601U */
+       if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
+               dev_warn(dev->dev, "Warning: eFUSE not present\n");
+
+       ret = mt7601u_init_hardware(dev);
+       if (ret)
+               goto err;
+       ret = mt7601u_register_device(dev);
+       if (ret)
+               goto err_hw;
+
+       set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
+
+       return 0;
+err_hw:
+       mt7601u_cleanup(dev);
+err:
+       usb_set_intfdata(usb_intf, NULL);
+       usb_put_dev(interface_to_usbdev(usb_intf));
+
+       destroy_workqueue(dev->stat_wq);
+       ieee80211_free_hw(dev->hw);
+       return ret;
+}
+
+static void mt7601u_disconnect(struct usb_interface *usb_intf)
+{
+       struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
+
+       ieee80211_unregister_hw(dev->hw);
+       mt7601u_cleanup(dev);
+
+       usb_set_intfdata(usb_intf, NULL);
+       usb_put_dev(interface_to_usbdev(usb_intf));
+
+       destroy_workqueue(dev->stat_wq);
+       ieee80211_free_hw(dev->hw);
+}
+
+static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
+{
+       struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
+
+       mt7601u_cleanup(dev);
+
+       return 0;
+}
+
+static int mt7601u_resume(struct usb_interface *usb_intf)
+{
+       struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
+
+       return mt7601u_init_hardware(dev);
+}
+
+MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
+MODULE_FIRMWARE(MT7601U_FIRMWARE);
+MODULE_LICENSE("GPL");
+
+static struct usb_driver mt7601u_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = mt7601u_device_table,
+       .probe          = mt7601u_probe,
+       .disconnect     = mt7601u_disconnect,
+       .suspend        = mt7601u_suspend,
+       .resume         = mt7601u_resume,
+       .reset_resume   = mt7601u_resume,
+       .soft_unbind    = 1,
+       .disable_hub_initiated_lpm = 1,
+};
+module_usb_driver(mt7601u_driver);
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.h b/drivers/net/wireless/mediatek/mt7601u/usb.h
new file mode 100644 (file)
index 0000000..49e188f
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT7601U_USB_H
+#define __MT7601U_USB_H
+
+#include "mt7601u.h"
+
+#define MT7601U_FIRMWARE       "mt7601u.bin"
+
+#define MT_VEND_REQ_MAX_RETRY  10
+#define MT_VEND_REQ_TOUT_MS    300
+
+#define MT_VEND_DEV_MODE_RESET 1
+
+enum mt_vendor_req {
+       MT_VEND_DEV_MODE = 1,
+       MT_VEND_WRITE = 2,
+       MT_VEND_MULTI_READ = 7,
+       MT_VEND_WRITE_FCE = 0x42,
+};
+
+enum mt_usb_ep_in {
+       MT_EP_IN_PKT_RX,
+       MT_EP_IN_CMD_RESP,
+       __MT_EP_IN_MAX,
+};
+
+enum mt_usb_ep_out {
+       MT_EP_OUT_INBAND_CMD,
+       MT_EP_OUT_AC_BK,
+       MT_EP_OUT_AC_BE,
+       MT_EP_OUT_AC_VI,
+       MT_EP_OUT_AC_VO,
+       MT_EP_OUT_HCCA,
+       __MT_EP_OUT_MAX,
+};
+
+static inline struct usb_device *mt7601u_to_usb_dev(struct mt7601u_dev *mt7601u)
+{
+       return interface_to_usbdev(to_usb_interface(mt7601u->dev));
+}
+
+static inline bool mt7601u_urb_has_error(struct urb *urb)
+{
+       return urb->status &&
+               urb->status != -ENOENT &&
+               urb->status != -ECONNRESET &&
+               urb->status != -ESHUTDOWN;
+}
+
+bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
+                          struct mt7601u_dma_buf *buf);
+void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf);
+int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
+                          struct mt7601u_dma_buf *buf, gfp_t gfp,
+                          usb_complete_t complete_fn, void *context);
+void mt7601u_complete_urb(struct urb *urb);
+
+int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
+                          const u8 direction, const u16 val, const u16 offset,
+                          void *buf, const size_t buflen);
+void mt7601u_vendor_reset(struct mt7601u_dev *dev);
+int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
+                            const u16 offset, const u32 val);
+
+#endif
diff --git a/drivers/net/wireless/mediatek/mt7601u/util.c b/drivers/net/wireless/mediatek/mt7601u/util.c
new file mode 100644 (file)
index 0000000..7c1787c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#include "mt7601u.h"
+
+void mt76_remove_hdr_pad(struct sk_buff *skb)
+{
+       int len = ieee80211_get_hdrlen_from_skb(skb);
+
+       memmove(skb->data + 2, skb->data, len);
+       skb_pull(skb, 2);
+}
+
+int mt76_insert_hdr_pad(struct sk_buff *skb)
+{
+       int len = ieee80211_get_hdrlen_from_skb(skb);
+       int ret;
+
+       if (len % 4 == 0)
+               return 0;
+
+       ret = skb_cow(skb, 2);
+       if (ret)
+               return ret;
+
+       skb_push(skb, 2);
+       memmove(skb->data, skb->data + 2, len);
+
+       skb->data[len] = 0;
+       skb->data[len + 1] = 0;
+       return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt7601u/util.h b/drivers/net/wireless/mediatek/mt7601u/util.h
new file mode 100644 (file)
index 0000000..b89140b
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ *
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef __MT76_UTIL_H
+#define __MT76_UTIL_H
+
+/*
+ * Power of two check, this will check
+ * if the mask that has been given contains and contiguous set of bits.
+ * Note that we cannot use the is_power_of_2() function since this
+ * check must be done at compile-time.
+ */
+#define is_power_of_two(x)     ( !((x) & ((x)-1)) )
+#define low_bit_mask(x)                ( ((x)-1) & ~(x) )
+#define is_valid_mask(x)       is_power_of_two(1LU + (x) + low_bit_mask(x))
+
+/*
+ * Macros to find first set bit in a variable.
+ * These macros behave the same as the __ffs() functions but
+ * the most important difference that this is done during
+ * compile-time rather then run-time.
+ */
+#define compile_ffs2(__x) \
+       __builtin_choose_expr(((__x) & 0x1), 0, 1)
+
+#define compile_ffs4(__x) \
+       __builtin_choose_expr(((__x) & 0x3), \
+                             (compile_ffs2((__x))), \
+                             (compile_ffs2((__x) >> 2) + 2))
+
+#define compile_ffs8(__x) \
+       __builtin_choose_expr(((__x) & 0xf), \
+                             (compile_ffs4((__x))), \
+                             (compile_ffs4((__x) >> 4) + 4))
+
+#define compile_ffs16(__x) \
+       __builtin_choose_expr(((__x) & 0xff), \
+                             (compile_ffs8((__x))), \
+                             (compile_ffs8((__x) >> 8) + 8))
+
+#define compile_ffs32(__x) \
+       __builtin_choose_expr(((__x) & 0xffff), \
+                             (compile_ffs16((__x))), \
+                             (compile_ffs16((__x) >> 16) + 16))
+
+/*
+ * This macro will check the requirements for the FIELD{8,16,32} macros
+ * The mask should be a constant non-zero contiguous set of bits which
+ * does not exceed the given typelimit.
+ */
+#define FIELD_CHECK(__mask) \
+       BUILD_BUG_ON(!(__mask) || !is_valid_mask(__mask))
+
+#define MT76_SET(_mask, _val)                                          \
+       ({                                                              \
+               FIELD_CHECK(_mask);                                     \
+               (((u32) (_val)) << compile_ffs32(_mask)) & _mask;       \
+       })
+
+#define MT76_GET(_mask, _val)                                          \
+       ({                                                              \
+               FIELD_CHECK(_mask);                                     \
+               (u32) (((_val) & _mask) >> compile_ffs32(_mask));       \
+       })
+
+#endif
index 3ab87a8551225625a7a0d92283deb77a2e0a7d5b..65cd461c88db5505a99d113a9650d26fd84ccb96 100644 (file)
@@ -134,8 +134,8 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
 
        chandef = priv->dfs_chandef;
        if (priv->wdev.cac_started) {
-               dev_dbg(priv->adapter->dev,
-                       "CAC timer finished; No radar detected\n");
+               mwifiex_dbg(priv->adapter, MSG,
+                           "CAC timer finished; No radar detected\n");
                cfg80211_cac_event(priv->netdev, &chandef,
                                   NL80211_RADAR_CAC_FINISHED,
                                   GFP_KERNEL);
@@ -161,9 +161,9 @@ int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
        cr_req->chan_desc.chan_width = radar_params->chandef->width;
        cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
 
-       dev_dbg(priv->adapter->dev,
-               "11h: issuing DFS Radar check for channel=%d\n",
-               radar_params->chandef->chan->hw_value);
+       mwifiex_dbg(priv->adapter, MSG,
+                   "11h: issuing DFS Radar check for channel=%d\n",
+                   radar_params->chandef->chan->hw_value);
 
        return 0;
 }
@@ -174,8 +174,8 @@ int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
 void mwifiex_abort_cac(struct mwifiex_private *priv)
 {
        if (priv->wdev.cac_started) {
-               dev_dbg(priv->adapter->dev,
-                       "Aborting delayed work for CAC.\n");
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Aborting delayed work for CAC.\n");
                cancel_delayed_work_sync(&priv->dfs_cac_work);
                cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
                                   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
@@ -199,7 +199,8 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
                                sizeof(u32));
 
        if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) {
-               dev_err(priv->adapter->dev, "Error in channel report event\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Error in channel report event\n");
                return -1;
        }
 
@@ -212,8 +213,8 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
                switch (le16_to_cpu(rpt->header.type)) {
                case TLV_TYPE_CHANRPT_11H_BASIC:
                        if (rpt->map.radar) {
-                               dev_notice(priv->adapter->dev,
-                                          "RADAR Detected on channel %d!\n",
+                               mwifiex_dbg(priv->adapter, MSG,
+                                           "RADAR Detected on channel %d!\n",
                                            priv->dfs_chandef.chan->hw_value);
                                cancel_delayed_work_sync(&priv->dfs_cac_work);
                                cfg80211_cac_event(priv->netdev,
@@ -242,16 +243,17 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
        rdr_event = (void *)(skb->data + sizeof(u32));
 
        if (le32_to_cpu(rdr_event->passed)) {
-               dev_notice(priv->adapter->dev,
-                          "radar detected; indicating kernel\n");
+               mwifiex_dbg(priv->adapter, MSG,
+                           "radar detected; indicating kernel\n");
                cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
                                     GFP_KERNEL);
-               dev_dbg(priv->adapter->dev, "regdomain: %d\n",
-                       rdr_event->reg_domain);
-               dev_dbg(priv->adapter->dev, "radar detection type: %d\n",
-                       rdr_event->det_type);
+               mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
+                           rdr_event->reg_domain);
+               mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
+                           rdr_event->det_type);
        } else {
-               dev_dbg(priv->adapter->dev, "false radar detection event!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "false radar detection event!\n");
        }
 
        return 0;
@@ -276,20 +278,20 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
 
        bss_cfg = &priv->bss_cfg;
        if (!bss_cfg->beacon_period) {
-               dev_err(priv->adapter->dev,
-                       "channel switch: AP already stopped\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "channel switch: AP already stopped\n");
                return;
        }
 
        mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef);
 
        if (mwifiex_config_start_uap(priv, bss_cfg)) {
-               dev_dbg(priv->adapter->dev,
-                       "Failed to start AP after channel switch\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start AP after channel switch\n");
                return;
        }
 
-       dev_notice(priv->adapter->dev,
-                  "indicating channel switch completion to kernel\n");
+       mwifiex_dbg(priv->adapter, MSG,
+                   "indicating channel switch completion to kernel\n");
        cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef);
 }
index 433bd6837c79042b3a5e7daa2bb20f594fd7dd28..8422986cd7a9137c171f706b123120a6e279d524 100644 (file)
@@ -42,7 +42,7 @@ int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
                                        priv->wdev.wiphy->bands[radio_type];
 
        if (WARN_ON_ONCE(!sband)) {
-               dev_err(priv->adapter->dev, "Invalid radio type!\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Invalid radio type!\n");
                return -EINVAL;
        }
 
@@ -184,7 +184,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
 
        tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr);
        if (tx_ba_tbl) {
-               dev_dbg(priv->adapter->dev, "info: BA stream complete\n");
+               mwifiex_dbg(priv->adapter, EVENT, "info: BA stream complete\n");
                tx_ba_tbl->ba_status = BA_SETUP_COMPLETE;
                if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
                    priv->add_ba_param.tx_amsdu &&
@@ -197,7 +197,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                        ra_list->ba_status = BA_SETUP_COMPLETE;
                }
        } else {
-               dev_err(priv->adapter->dev, "BA stream not created\n");
+               mwifiex_dbg(priv->adapter, ERROR, "BA stream not created\n");
        }
 
        return 0;
@@ -224,7 +224,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
        tx_buf->action = cpu_to_le16(action);
        switch (action) {
        case HostCmd_ACT_GEN_SET:
-               dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: set tx_buf=%d\n", *buf_size);
                tx_buf->buff_size = cpu_to_le16(*buf_size);
                break;
        case HostCmd_ACT_GEN_GET:
@@ -466,7 +467,8 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
            mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
                return;
 
-       dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
 
        list_del(&tx_ba_tsr_tbl->list);
 
@@ -563,7 +565,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
        unsigned long flags;
        u16 block_ack_param_set;
 
-       dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
+       mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid);
 
        if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
@@ -575,9 +577,9 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
                sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
                if (!sta_ptr) {
                        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-                       dev_warn(priv->adapter->dev,
-                                "BA setup with unknown TDLS peer %pM!\n",
-                               peer_mac);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "BA setup with unknown TDLS peer %pM!\n",
+                                   peer_mac);
                        return -1;
                }
                if (sta_ptr->is_11ac_enabled)
@@ -706,8 +708,8 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
        spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
        list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
                rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
-               dev_dbg(priv->adapter->dev, "data: %s tid=%d\n",
-                       __func__, rx_reo_tbl->tid);
+               mwifiex_dbg(priv->adapter, DATA, "data: %s tid=%d\n",
+                           __func__, rx_reo_tbl->tid);
                memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN);
                rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu;
                rx_reo_tbl++;
index 6183e255e62ac380a614cb593cb226d27da5909d..f7c717253a664aaa7170b3216890ebd1b22ad295 100644 (file)
@@ -187,7 +187,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
        skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size,
                                               GFP_ATOMIC | GFP_DMA);
        if (!skb_aggr) {
-               dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__);
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
                return -1;
@@ -297,13 +296,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
                tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
-               dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
                break;
        case -1:
                if (adapter->iface_type != MWIFIEX_PCIE)
                        adapter->data_sent = false;
-               dev_err(adapter->dev, "%s: host_to_card failed: %#x\n",
-                       __func__, ret);
+               mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n",
+                           __func__, ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
                return 0;
index f75f8acfaca0332cef494e8146d4e331db683385..39d7a957674c2b6cd83d3593e7a10a08745ad56d 100644 (file)
@@ -51,8 +51,8 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
                        rx_skb = __skb_dequeue(&list);
                        ret = mwifiex_recv_packet(priv, rx_skb);
                        if (ret == -1)
-                               dev_err(priv->adapter->dev,
-                                       "Rx of A-MSDU failed");
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Rx of A-MSDU failed");
                }
                return 0;
        }
@@ -304,7 +304,7 @@ mwifiex_flush_data(unsigned long context)
        if (seq_num < 0)
                return;
 
-       dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", seq_num);
+       mwifiex_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num);
        start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1);
        mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr,
                                                 start_win);
@@ -367,8 +367,9 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
        }
        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 
-       dev_dbg(priv->adapter->dev, "info: last_seq=%d start_win=%d\n",
-               last_seq, new_node->start_win);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: last_seq=%d start_win=%d\n",
+                   last_seq, new_node->start_win);
 
        if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
            last_seq >= new_node->start_win) {
@@ -382,8 +383,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
                                        GFP_KERNEL);
        if (!new_node->rx_reorder_ptr) {
                kfree((u8 *) new_node);
-               dev_err(priv->adapter->dev,
-                       "%s: failed to alloc reorder_ptr\n", __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: failed to alloc reorder_ptr\n", __func__);
                return;
        }
 
@@ -467,9 +468,9 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
                                                cmd_addba_req->peer_mac_addr);
                if (!sta_ptr) {
                        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-                       dev_warn(priv->adapter->dev,
-                                "BA setup with unknown TDLS peer %pM!\n",
-                                cmd_addba_req->peer_mac_addr);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "BA setup with unknown TDLS peer %pM!\n",
+                                   cmd_addba_req->peer_mac_addr);
                        return -1;
                }
                if (sta_ptr->is_11ac_enabled)
@@ -573,14 +574,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
        }
 
        if (tbl->flags & RXREOR_FORCE_NO_DROP) {
-               dev_dbg(priv->adapter->dev,
-                       "RXREOR_FORCE_NO_DROP when HS is activated\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "RXREOR_FORCE_NO_DROP when HS is activated\n");
                tbl->flags &= ~RXREOR_FORCE_NO_DROP;
        } else if (init_window_shift && seq_num < start_win &&
                   seq_num >= tbl->init_win) {
-               dev_dbg(priv->adapter->dev,
-                       "Sender TID sequence number reset %d->%d for SSN %d\n",
-                       start_win, seq_num, tbl->init_win);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Sender TID sequence number reset %d->%d for SSN %d\n",
+                           start_win, seq_num, tbl->init_win);
                tbl->start_win = start_win = seq_num;
                end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
        } else {
@@ -668,23 +669,23 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
        else
                cleanup_rx_reorder_tbl = (initiator) ? false : true;
 
-       dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d initiator=%d\n",
-               peer_mac, tid, initiator);
+       mwifiex_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=%d initiator=%d\n",
+                   peer_mac, tid, initiator);
 
        if (cleanup_rx_reorder_tbl) {
                tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
                                                                 peer_mac);
                if (!tbl) {
-                       dev_dbg(priv->adapter->dev,
-                               "event: TID, TA not found in table\n");
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: TID, TA not found in table\n");
                        return;
                }
                mwifiex_del_rx_reorder_entry(priv, tbl);
        } else {
                ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
                if (!ptx_tbl) {
-                       dev_dbg(priv->adapter->dev,
-                               "event: TID, RA not found in table\n");
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: TID, RA not found in table\n");
                        return;
                }
                ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac);
@@ -721,8 +722,8 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
         * the stream
         */
        if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
-               dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n",
-                       add_ba_rsp->peer_mac_addr, tid);
+               mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n",
+                           add_ba_rsp->peer_mac_addr, tid);
 
                tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
                                                     add_ba_rsp->peer_mac_addr);
@@ -746,8 +747,8 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
                        tbl->amsdu = false;
        }
 
-       dev_dbg(priv->adapter->dev,
-               "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
                add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
 
        return 0;
index aa01c9bc77f916db68de7c51f8f848d45dc8fa26..48edf387683ebbd79a98f5257689f816378be3cf 100644 (file)
@@ -12,6 +12,7 @@ config MWIFIEX_SDIO
        tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897"
        depends on MWIFIEX && MMC
        select FW_LOADER
+       select WANT_DEV_COREDUMP
        ---help---
          This adds support for wireless adapters based on Marvell
          8786/8787/8797/8887/8897 chipsets with SDIO interface.
@@ -23,6 +24,7 @@ config MWIFIEX_PCIE
        tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897"
        depends on MWIFIEX && PCI
        select FW_LOADER
+       select WANT_DEV_COREDUMP
        ---help---
          This adds support for wireless adapters based on Marvell
          8766/8897 chipsets with PCIe interface.
index 31928caeeed225edbae57f38bd7488edee7b726d..2f0f9b5609d0139a301f7e57866f212cc1daefe1 100644 (file)
@@ -230,9 +230,9 @@ getlog
 
        cat getlog
 
-fw_dump
-       This command is used to dump firmware memory into files.
-       Separate file will be created for each memory segment.
+device_dump
+       This command is used to dump driver information and firmware memory
+       segments.
        Usage:
 
        cat fw_dump
index bf9020ff2d33cf1cf9dc2c044f06a403b655e593..4eecedadefbff64c7a2656444809c21470ab73e8 100644 (file)
@@ -104,11 +104,11 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
        const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 
        if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
-               wiphy_err(wiphy, "deleting the crypto keys\n");
+               mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
                return -EFAULT;
        }
 
-       wiphy_dbg(wiphy, "info: crypto keys deleted\n");
+       mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");
        return 0;
 }
 
@@ -163,7 +163,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 
        if (!buf || !len) {
-               wiphy_err(wiphy, "invalid buffer and length\n");
+               mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");
                return -EFAULT;
        }
 
@@ -172,8 +172,8 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
            ieee80211_is_probe_resp(mgmt->frame_control)) {
                /* Since we support offload probe resp, we need to skip probe
                 * resp in AP or GO mode */
-               wiphy_dbg(wiphy,
-                         "info: skip to send probe resp in AP or GO mode\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: skip to send probe resp in AP or GO mode\n");
                return 0;
        }
 
@@ -183,7 +183,8 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                            pkt_len + sizeof(pkt_len));
 
        if (!skb) {
-               wiphy_err(wiphy, "allocate skb failed for management frame\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
                return -ENOMEM;
        }
 
@@ -206,7 +207,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
        mwifiex_queue_tx_pkt(priv, skb);
 
-       wiphy_dbg(wiphy, "info: management frame transmitted\n");
+       mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");
        return 0;
 }
 
@@ -231,7 +232,7 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
                mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
                                 HostCmd_ACT_GEN_SET, 0,
                                 &priv->mgmt_frame_mask, false);
-               wiphy_dbg(wiphy, "info: mgmt frame registered\n");
+               mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");
        }
 }
 
@@ -248,13 +249,14 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
        int ret;
 
        if (!chan || !cookie) {
-               wiphy_err(wiphy, "Invalid parameter for ROC\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");
                return -EINVAL;
        }
 
        if (priv->roc_cfg.cookie) {
-               wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llx\n",
-                         priv->roc_cfg.cookie);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ongoing ROC, cookie = 0x%llx\n",
+                           priv->roc_cfg.cookie);
                return -EBUSY;
        }
 
@@ -269,7 +271,8 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
                cfg80211_ready_on_channel(wdev, *cookie, chan,
                                          duration, GFP_ATOMIC);
 
-               wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ROC, cookie = 0x%llx\n", *cookie);
        }
 
        return ret;
@@ -298,7 +301,8 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
 
                memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
 
-               wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: cancel ROC, cookie = 0x%llx\n", cookie);
        }
 
        return ret;
@@ -344,8 +348,8 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
        u32 ps_mode;
 
        if (timeout)
-               wiphy_dbg(wiphy,
-                         "info: ignore timeout value for IEEE Power Save\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ignore timeout value for IEEE Power Save\n");
 
        ps_mode = enabled;
 
@@ -370,7 +374,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
                priv->wep_key_curr_index = key_index;
        } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
                                      NULL, 0)) {
-               wiphy_err(wiphy, "set default Tx key index\n");
+               mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");
                return -EFAULT;
        }
 
@@ -407,7 +411,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
 
        if (mwifiex_set_encode(priv, params, params->key, params->key_len,
                               key_index, peer_mac, 0)) {
-               wiphy_err(wiphy, "crypto keys added\n");
+               mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");
                return -EFAULT;
        }
 
@@ -442,7 +446,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 
        band = mwifiex_band_to_radio_type(adapter->config_bands);
        if (!wiphy->bands[band]) {
-               wiphy_err(wiphy, "11D: setting domain info in FW\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "11D: setting domain info in FW\n");
                return -1;
        }
 
@@ -493,7 +498,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               wiphy_err(wiphy, "11D: setting domain info in FW\n");
+               mwifiex_dbg(adapter, INFO,
+                           "11D: setting domain info in FW\n");
                return -1;
        }
 
@@ -516,9 +522,9 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy,
        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
        struct mwifiex_private *priv = mwifiex_get_priv(adapter,
                                                        MWIFIEX_BSS_ROLE_ANY);
-
-       wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n",
-                 request->alpha2[0], request->alpha2[1]);
+       mwifiex_dbg(adapter, INFO,
+                   "info: cfg80211 regulatory domain callback for %c%c\n",
+                   request->alpha2[0], request->alpha2[1]);
 
        switch (request->initiator) {
        case NL80211_REGDOM_SET_BY_DRIVER:
@@ -527,8 +533,9 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy,
        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
                break;
        default:
-               wiphy_err(wiphy, "unknown regdom initiator: %d\n",
-                         request->initiator);
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown regdom initiator: %d\n",
+                           request->initiator);
                return;
        }
 
@@ -597,8 +604,8 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
        switch (priv->bss_role) {
        case MWIFIEX_BSS_ROLE_UAP:
                if (priv->bss_started) {
-                       dev_err(adapter->dev,
-                               "cannot change wiphy params when bss started");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot change wiphy params when bss started");
                        return -EINVAL;
                }
 
@@ -622,15 +629,16 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 
                kfree(bss_cfg);
                if (ret) {
-                       wiphy_err(wiphy, "Failed to set wiphy phy params\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to set wiphy phy params\n");
                        return ret;
                }
                break;
 
                case MWIFIEX_BSS_ROLE_STA:
                if (priv->media_connected) {
-                       dev_err(adapter->dev,
-                               "cannot change wiphy params when connected");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot change wiphy params when connected");
                        return -EINVAL;
                }
                if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
@@ -724,8 +732,8 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
        if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
                             HostCmd_ACT_GEN_SET, 0,
                             &priv->mgmt_frame_mask, false)) {
-               dev_warn(priv->adapter->dev,
-                        "could not unregister mgmt frame rx\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "could not unregister mgmt frame rx\n");
                return -1;
        }
 
@@ -789,9 +797,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "%s: changing to %d not supported\n",
-                       dev->name, type);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: changing to %d not supported\n",
+                           dev->name, type);
                return -EOPNOTSUPP;
        }
 
@@ -824,12 +832,13 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
 
        if (adapter->curr_iface_comb.p2p_intf ==
            adapter->iface_limit.p2p_intf) {
-               dev_err(adapter->dev,
-                       "cannot create multiple P2P ifaces\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple P2P ifaces\n");
                return -1;
        }
 
-       dev_dbg(priv->adapter->dev, "%s: changing role to p2p\n", dev->name);
+       mwifiex_dbg(adapter, INFO,
+                   "%s: changing role to p2p\n", dev->name);
 
        if (mwifiex_deinit_priv_params(priv))
                return -1;
@@ -846,9 +855,9 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
                        return -EFAULT;
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "%s: changing to %d not supported\n",
-                       dev->name, type);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: changing to %d not supported\n",
+                           dev->name, type);
                return -EOPNOTSUPP;
        }
 
@@ -897,17 +906,17 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
             curr_iftype != NL80211_IFTYPE_P2P_GO) &&
            (adapter->curr_iface_comb.sta_intf ==
             adapter->iface_limit.sta_intf)) {
-               dev_err(adapter->dev,
-                       "cannot create multiple station/adhoc ifaces\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple station/adhoc ifaces\n");
                return -1;
        }
 
        if (type == NL80211_IFTYPE_STATION)
-               dev_notice(adapter->dev,
-                          "%s: changing role to station\n", dev->name);
+               mwifiex_dbg(adapter, INFO,
+                           "%s: changing role to station\n", dev->name);
        else
-               dev_notice(adapter->dev,
-                          "%s: changing role to adhoc\n", dev->name);
+               mwifiex_dbg(adapter, INFO,
+                           "%s: changing role to adhoc\n", dev->name);
 
        if (mwifiex_deinit_priv_params(priv))
                return -1;
@@ -954,12 +963,13 @@ mwifiex_change_vif_to_ap(struct net_device *dev,
 
        if (adapter->curr_iface_comb.uap_intf ==
            adapter->iface_limit.uap_intf) {
-               dev_err(adapter->dev,
-                       "cannot create multiple AP ifaces\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create multiple AP ifaces\n");
                return -1;
        }
 
-       dev_notice(adapter->dev, "%s: changing role to AP\n", dev->name);
+       mwifiex_dbg(adapter, INFO,
+                   "%s: changing role to AP\n", dev->name);
 
        if (mwifiex_deinit_priv_params(priv))
                return -1;
@@ -1020,12 +1030,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
                                                        flags, params);
                case NL80211_IFTYPE_UNSPECIFIED:
-                       wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as IBSS\n", dev->name);
                case NL80211_IFTYPE_ADHOC:      /* This shouldn't happen */
                        return 0;
                default:
-                       wiphy_err(wiphy, "%s: changing to %d not supported\n",
-                                 dev->name, type);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -1048,12 +1060,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
                                                        flags, params);
                case NL80211_IFTYPE_UNSPECIFIED:
-                       wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as STA\n", dev->name);
                case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
                        return 0;
                default:
-                       wiphy_err(wiphy, "%s: changing to %d not supported\n",
-                                 dev->name, type);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -1070,12 +1084,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                        return mwifiex_change_vif_to_p2p(dev, curr_iftype,
                                                         type, flags, params);
                case NL80211_IFTYPE_UNSPECIFIED:
-                       wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as AP\n", dev->name);
                case NL80211_IFTYPE_AP:         /* This shouldn't happen */
                        return 0;
                default:
-                       wiphy_err(wiphy, "%s: changing to %d not supported\n",
-                                 dev->name, type);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -1100,19 +1116,22 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
                                                        flags, params);
                case NL80211_IFTYPE_UNSPECIFIED:
-                       wiphy_warn(wiphy, "%s: kept type as P2P\n", dev->name);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "%s: kept type as P2P\n", dev->name);
                case NL80211_IFTYPE_P2P_CLIENT:
                case NL80211_IFTYPE_P2P_GO:
                        return 0;
                default:
-                       wiphy_err(wiphy, "%s: changing to %d not supported\n",
-                                 dev->name, type);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "%s: changing to %d not supported\n",
+                                   dev->name, type);
                        return -EOPNOTSUPP;
                }
                break;
        default:
-               wiphy_err(wiphy, "%s: unknown iftype: %d\n",
-                         dev->name, dev->ieee80211_ptr->iftype);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: unknown iftype: %d\n",
+                           dev->name, dev->ieee80211_ptr->iftype);
                return -EOPNOTSUPP;
        }
 
@@ -1206,12 +1225,14 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
        /* Get signal information from the firmware */
        if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                             HostCmd_ACT_GEN_GET, 0, NULL, true)) {
-               dev_err(priv->adapter->dev, "failed to get signal information\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "failed to get signal information\n");
                return -EFAULT;
        }
 
        if (mwifiex_drv_get_data_rate(priv, &rate)) {
-               dev_err(priv->adapter->dev, "getting data rate\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "getting data rate error\n");
                return -EFAULT;
        }
 
@@ -1295,7 +1316,7 @@ mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
        struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
        enum ieee80211_band band;
 
-       dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx);
+       mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);
 
        memset(survey, 0, sizeof(struct survey_info));
 
@@ -1472,8 +1493,8 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
        struct mwifiex_adapter *adapter = priv->adapter;
 
        if (!priv->media_connected) {
-               dev_err(adapter->dev,
-                       "Can not set Tx data rate in disconnected state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Can not set Tx data rate in disconnected state\n");
                return -EINVAL;
        }
 
@@ -1556,17 +1577,20 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
-               wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: bss_type mismatched\n", __func__);
                return -EINVAL;
        }
 
        if (!priv->bss_started) {
-               wiphy_err(wiphy, "%s: bss not started\n", __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: bss not started\n", __func__);
                return -EINVAL;
        }
 
        if (mwifiex_set_mgmt_ies(priv, data)) {
-               wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: setting mgmt ies failed\n", __func__);
                return -EFAULT;
        }
 
@@ -1594,7 +1618,8 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
        if (!params->mac || is_broadcast_ether_addr(params->mac))
                return 0;
 
-       wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, params->mac);
+       mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",
+                   __func__, params->mac);
 
        eth_zero_addr(deauth_mac);
 
@@ -1687,14 +1712,16 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        mwifiex_abort_cac(priv);
 
        if (mwifiex_del_mgmt_ies(priv))
-               wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to delete mgmt IEs!\n");
 
        priv->ap_11n_enabled = 0;
        memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-               wiphy_err(wiphy, "Failed to stop the BSS\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to stop the BSS\n");
                return -1;
        }
 
@@ -1756,7 +1783,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
        if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
                kfree(bss_cfg);
-               wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to parse secuirty parameters!\n");
                return -1;
        }
 
@@ -1778,17 +1806,19 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
        if (mwifiex_is_11h_active(priv) &&
            !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
                                           priv->bss_mode)) {
-               dev_dbg(priv->adapter->dev, "Disable 11h extensions in FW\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Disable 11h extensions in FW\n");
                if (mwifiex_11h_activate(priv, false)) {
-                       dev_err(priv->adapter->dev,
-                               "Failed to disable 11h extensions!!");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to disable 11h extensions!!");
                        return -1;
                }
                priv->state_11h.is_11h_active = true;
        }
 
        if (mwifiex_config_start_uap(priv, bss_cfg)) {
-               wiphy_err(wiphy, "Failed to start AP\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start AP\n");
                kfree(bss_cfg);
                return -1;
        }
@@ -1816,8 +1846,9 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
        if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
-       wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
-               " reason code %d\n", priv->cfg_bssid, reason_code);
+       mwifiex_dbg(priv->adapter, MSG,
+                   "info: successfully disconnected from %pM:\t"
+                   "reason code %d\n", priv->cfg_bssid, reason_code);
 
        eth_zero_addr(priv->cfg_bssid);
        priv->hs2_enabled = false;
@@ -1899,13 +1930,13 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
 
        req_ssid.ssid_len = ssid_len;
        if (ssid_len > IEEE80211_MAX_SSID_LEN) {
-               dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
+               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
                return -EINVAL;
        }
 
        memcpy(req_ssid.ssid, ssid, ssid_len);
        if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
-               dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
+               mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
                return -EINVAL;
        }
 
@@ -1959,9 +1990,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
 
        if (sme->key) {
                if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
-                       dev_dbg(priv->adapter->dev,
-                               "info: setting wep encryption"
-                               with key len %d\n", sme->key_len);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: setting wep encryption\t"
+                                   "with key len %d\n", sme->key_len);
                        priv->wep_key_curr_index = sme->key_idx;
                        ret = mwifiex_set_encode(priv, NULL, sme->key,
                                                 sme->key_len, sme->key_idx,
@@ -1978,7 +2009,7 @@ done:
                if (is_scanning_required) {
                        /* Do specific SSID scanning */
                        if (mwifiex_request_scan(priv, &req_ssid)) {
-                               dev_err(priv->adapter->dev, "scan error\n");
+                               mwifiex_dbg(priv->adapter, ERROR, "scan error\n");
                                return -EFAULT;
                        }
                }
@@ -1997,15 +2028,15 @@ done:
 
                if (!bss) {
                        if (is_scanning_required) {
-                               dev_warn(priv->adapter->dev,
-                                        "assoc: requested bss not found in scan results\n");
+                               mwifiex_dbg(priv->adapter, WARN,
+                                           "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' bssid %pM\n",
-                               (char *) req_ssid.ssid, bss->bssid);
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "info: trying to associate to '%s' bssid %pM\n",
+                                   (char *)req_ssid.ssid, bss->bssid);
                        memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
                        break;
                }
@@ -2041,26 +2072,29 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        int ret;
 
        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
-               wiphy_err(wiphy,
-                         "%s: reject infra assoc request in non-STA role\n",
-                         dev->name);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: reject infra assoc request in non-STA role\n",
+                           dev->name);
                return -EINVAL;
        }
 
        if (priv->wdev.current_bss) {
-               wiphy_warn(wiphy, "%s: already connected\n", dev->name);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: already connected\n", dev->name);
                return -EALREADY;
        }
 
        if (adapter->surprise_removed || adapter->is_cmd_timedout) {
-               wiphy_err(wiphy,
-                         "%s: Ignore connection. Card removed or FW in bad state\n",
-                         dev->name);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: Ignore connection.\t"
+                           "Card removed or FW in bad state\n",
+                           dev->name);
                return -EFAULT;
        }
 
-       wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
-                 (char *) sme->ssid, sme->bssid);
+       mwifiex_dbg(adapter, INFO,
+                   "info: Trying to associate to %s and bssid %pM\n",
+                   (char *)sme->ssid, sme->bssid);
 
        ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
                                     priv->bss_mode, sme->channel, sme, 0);
@@ -2068,17 +2102,17 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
                                        NULL, 0, WLAN_STATUS_SUCCESS,
                                        GFP_KERNEL);
-               dev_dbg(priv->adapter->dev,
-                       "info: associated to bssid %pM successfully\n",
-                       priv->cfg_bssid);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "info: associated to bssid %pM successfully\n",
+                           priv->cfg_bssid);
                if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
                    priv->adapter->auto_tdls &&
                    priv->bss_type == MWIFIEX_BSS_TYPE_STA)
                        mwifiex_setup_auto_tdls_timer(priv);
        } else {
-               dev_dbg(priv->adapter->dev,
-                       "info: association to bssid %pM failed\n",
-                       priv->cfg_bssid);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: association to bssid %pM failed\n",
+                           priv->cfg_bssid);
                eth_zero_addr(priv->cfg_bssid);
 
                if (ret > 0)
@@ -2105,7 +2139,6 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
                                   struct cfg80211_ibss_params *params)
 {
-       struct wiphy *wiphy = priv->wdev.wiphy;
        struct mwifiex_adapter *adapter = priv->adapter;
        int index = 0, i;
        u8 config_bands = 0;
@@ -2162,8 +2195,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
        priv->adhoc_channel = ieee80211_frequency_to_channel(
                                params->chandef.chan->center_freq);
 
-       wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
-                 config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
+       mwifiex_dbg(adapter, INFO,
+                   "info: set ibss band %d, chan %d, chan offset %d\n",
+                   config_bands, priv->adhoc_channel,
+                   adapter->sec_chan_offset);
 
        return 0;
 }
@@ -2182,13 +2217,15 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        int ret = 0;
 
        if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
-               wiphy_err(wiphy, "request to join ibss received "
-                               "when station is not in ibss mode\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "request to join ibss received\t"
+                           "when station is not in ibss mode\n");
                goto done;
        }
 
-       wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
-                 (char *) params->ssid, params->bssid);
+       mwifiex_dbg(priv->adapter, MSG,
+                   "info: trying to join to %s and bssid %pM\n",
+                   (char *)params->ssid, params->bssid);
 
        mwifiex_set_ibss_params(priv, params);
 
@@ -2200,12 +2237,12 @@ done:
        if (!ret) {
                cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
                                     params->chandef.chan, GFP_KERNEL);
-               dev_dbg(priv->adapter->dev,
-                       "info: joined/created adhoc network with bssid"
-                       %pM successfully\n", priv->cfg_bssid);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "info: joined/created adhoc network with bssid\t"
+                           "%pM successfully\n", priv->cfg_bssid);
        } else {
-               dev_dbg(priv->adapter->dev,
-                       "info: failed creating/joining adhoc network\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: failed creating/joining adhoc network\n");
        }
 
        return ret;
@@ -2222,8 +2259,8 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
-       wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
-                 priv->cfg_bssid);
+       mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",
+                   priv->cfg_bssid);
        if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
@@ -2250,13 +2287,15 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
        struct ieee_types_header *ie;
        struct mwifiex_user_scan_cfg *user_scan_cfg;
 
-       wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "info: received scan request on %s\n", dev->name);
 
        /* Block scan request if scan operation or scan cleanup when interface
         * is disabled is in process
         */
        if (priv->scan_request || priv->scan_aborting) {
-               dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
+               mwifiex_dbg(priv->adapter, WARN,
+                           "cmd: Scan already in process..\n");
                return -EBUSY;
        }
 
@@ -2308,7 +2347,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
        ret = mwifiex_scan_networks(priv, user_scan_cfg);
        kfree(user_scan_cfg);
        if (ret) {
-               dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "scan failed: %d\n", ret);
                priv->scan_aborting = false;
                priv->scan_request = NULL;
                return ret;
@@ -2454,15 +2494,15 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        case NL80211_IFTYPE_ADHOC:
                if (adapter->curr_iface_comb.sta_intf ==
                    adapter->iface_limit.sta_intf) {
-                       wiphy_err(wiphy,
-                                 "cannot create multiple sta/adhoc ifaces\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple sta/adhoc ifaces\n");
                        return ERR_PTR(-EINVAL);
                }
 
                priv = mwifiex_get_unused_priv(adapter);
                if (!priv) {
-                       wiphy_err(wiphy,
-                                 "could not get free private struct\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
                        return ERR_PTR(-EFAULT);
                }
 
@@ -2484,15 +2524,15 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        case NL80211_IFTYPE_AP:
                if (adapter->curr_iface_comb.uap_intf ==
                    adapter->iface_limit.uap_intf) {
-                       wiphy_err(wiphy,
-                                 "cannot create multiple AP ifaces\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple AP ifaces\n");
                        return ERR_PTR(-EINVAL);
                }
 
                priv = mwifiex_get_unused_priv(adapter);
                if (!priv) {
-                       wiphy_err(wiphy,
-                                 "could not get free private struct\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
                        return ERR_PTR(-EFAULT);
                }
 
@@ -2511,15 +2551,15 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        case NL80211_IFTYPE_P2P_CLIENT:
                if (adapter->curr_iface_comb.p2p_intf ==
                    adapter->iface_limit.p2p_intf) {
-                       wiphy_err(wiphy,
-                                 "cannot create multiple P2P ifaces\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create multiple P2P ifaces\n");
                        return ERR_PTR(-EINVAL);
                }
 
                priv = mwifiex_get_unused_priv(adapter);
                if (!priv) {
-                       wiphy_err(wiphy,
-                                 "could not get free private struct\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not get free private struct\n");
                        return ERR_PTR(-EFAULT);
                }
 
@@ -2550,7 +2590,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
                break;
        default:
-               wiphy_err(wiphy, "type not supported\n");
+               mwifiex_dbg(adapter, ERROR, "type not supported\n");
                return ERR_PTR(-EINVAL);
        }
 
@@ -2558,7 +2598,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                               name_assign_type, ether_setup,
                               IEEE80211_NUM_ACS, 1);
        if (!dev) {
-               wiphy_err(wiphy, "no memory available for netdevice\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "no memory available for netdevice\n");
                memset(&priv->wdev, 0, sizeof(priv->wdev));
                priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2599,7 +2640,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
        /* Register network device */
        if (register_netdevice(dev)) {
-               wiphy_err(wiphy, "cannot register virtual network device\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
                free_netdev(dev);
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
                priv->netdev = NULL;
@@ -2613,7 +2655,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                                                  WQ_MEM_RECLAIM |
                                                  WQ_UNBOUND, 1, name);
        if (!priv->dfs_cac_workqueue) {
-               wiphy_err(wiphy, "cannot register virtual network device\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
                free_netdev(dev);
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
                priv->netdev = NULL;
@@ -2628,7 +2671,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                                                      WQ_HIGHPRI | WQ_UNBOUND |
                                                      WQ_MEM_RECLAIM, 1, name);
        if (!priv->dfs_chan_sw_workqueue) {
-               wiphy_err(wiphy, "cannot register virtual network device\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register virtual network device\n");
                free_netdev(dev);
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
                priv->netdev = NULL;
@@ -2642,7 +2686,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
        sema_init(&priv->async_sem, 1);
 
-       dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: Marvell 802.11 Adapter\n", dev->name);
 
 #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_init(priv);
@@ -2661,7 +2706,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                adapter->curr_iface_comb.p2p_intf++;
                break;
        default:
-               wiphy_err(wiphy, "type not supported\n");
+               mwifiex_dbg(adapter, ERROR, "type not supported\n");
                return ERR_PTR(-EINVAL);
        }
 
@@ -2721,7 +2766,8 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
                adapter->curr_iface_comb.p2p_intf++;
                break;
        default:
-               dev_err(adapter->dev, "del_virtual_intf: type not supported\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "del_virtual_intf: type not supported\n");
                break;
        }
 
@@ -2839,7 +2885,8 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
                if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
                                        byte_seq,
                                        MWIFIEX_MEF_MAX_BYTESEQ)) {
-                       dev_err(priv->adapter->dev, "Pattern not supported\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Pattern not supported\n");
                        kfree(mef_entry);
                        return -EOPNOTSUPP;
                }
@@ -2954,21 +3001,22 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
        mwifiex_cancel_all_pending_cmd(adapter);
 
        if (!wowlan) {
-               dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "None of the WOWLAN triggers enabled\n");
                return 0;
        }
 
        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
 
        if (!priv->media_connected) {
-               dev_warn(adapter->dev,
-                        "Can not configure WOWLAN in disconnected state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Can not configure WOWLAN in disconnected state\n");
                return 0;
        }
 
        ret = mwifiex_set_mef_filter(priv, wowlan);
        if (ret) {
-               dev_err(adapter->dev, "Failed to set MEF filter\n");
+               mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");
                return ret;
        }
 
@@ -2981,7 +3029,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
                ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
                                            MWIFIEX_SYNC_CMD, &hs_cfg);
                if (ret) {
-                       dev_err(adapter->dev, "Failed to set HS params\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to set HS params\n");
                        return ret;
                }
        }
@@ -3041,7 +3090,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
                if (!mwifiex_is_pattern_supported(&crule->patterns[i],
                                                  byte_seq,
                                                MWIFIEX_COALESCE_MAX_BYTESEQ)) {
-                       dev_err(priv->adapter->dev, "Pattern not supported\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Pattern not supported\n");
                        return -EOPNOTSUPP;
                }
 
@@ -3050,8 +3100,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
 
                        pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
                        if (pkt_type && mrule->pkt_type) {
-                               dev_err(priv->adapter->dev,
-                                       "Multiple packet types not allowed\n");
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Multiple packet types not allowed\n");
                                return -EOPNOTSUPP;
                        } else if (pkt_type) {
                                mrule->pkt_type = pkt_type;
@@ -3074,8 +3124,8 @@ mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
        }
 
        if (!mrule->pkt_type) {
-               dev_err(priv->adapter->dev,
-                       "Packet type can not be determined\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Packet type can not be determined\n");
                return -EOPNOTSUPP;
        }
 
@@ -3093,8 +3143,8 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
 
        memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
        if (!coalesce) {
-               dev_dbg(adapter->dev,
-                       "Disable coalesce and reset all previous rules\n");
+               mwifiex_dbg(adapter, WARN,
+                           "Disable coalesce and reset all previous rules\n");
                return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
                                        HostCmd_ACT_GEN_SET, 0,
                                        &coalesce_cfg, true);
@@ -3105,8 +3155,8 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
                ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
                                                      &coalesce_cfg.rule[i]);
                if (ret) {
-                       dev_err(priv->adapter->dev,
-                               "Recheck the patterns provided for rule %d\n",
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Recheck the patterns provided for rule %d\n",
                                i + 1);
                        return ret;
                }
@@ -3138,9 +3188,9 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
        switch (action_code) {
        case WLAN_TDLS_SETUP_REQUEST:
-               dev_dbg(priv->adapter->dev,
-                       "Send TDLS Setup Request to %pM status_code=%d\n", peer,
-                        status_code);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Setup Request to %pM status_code=%d\n",
+                           peer, status_code);
                mwifiex_add_auto_tdls_peer(priv, peer);
                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
@@ -3148,45 +3198,45 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
                break;
        case WLAN_TDLS_SETUP_RESPONSE:
                mwifiex_add_auto_tdls_peer(priv, peer);
-               dev_dbg(priv->adapter->dev,
-                       "Send TDLS Setup Response to %pM status_code=%d\n",
-                       peer, status_code);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Setup Response to %pM status_code=%d\n",
+                           peer, status_code);
                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
                                                   extra_ies, extra_ies_len);
                break;
        case WLAN_TDLS_SETUP_CONFIRM:
-               dev_dbg(priv->adapter->dev,
-                       "Send TDLS Confirm to %pM status_code=%d\n", peer,
-                       status_code);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Confirm to %pM status_code=%d\n", peer,
+                           status_code);
                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
                                                   extra_ies, extra_ies_len);
                break;
        case WLAN_TDLS_TEARDOWN:
-               dev_dbg(priv->adapter->dev, "Send TDLS Tear down to %pM\n",
-                       peer);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Tear down to %pM\n", peer);
                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
                                                   extra_ies, extra_ies_len);
                break;
        case WLAN_TDLS_DISCOVERY_REQUEST:
-               dev_dbg(priv->adapter->dev,
-                       "Send TDLS Discovery Request to %pM\n", peer);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Discovery Request to %pM\n", peer);
                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
                                                   extra_ies, extra_ies_len);
                break;
        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-               dev_dbg(priv->adapter->dev,
-                       "Send TDLS Discovery Response to %pM\n", peer);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "Send TDLS Discovery Response to %pM\n", peer);
                ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
                                                   dialog_token, status_code,
                                                   extra_ies, extra_ies_len);
                break;
        default:
-               dev_warn(priv->adapter->dev,
-                        "Unknown TDLS mgmt/action frame %pM\n", peer);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS mgmt/action frame %pM\n", peer);
                ret = -EINVAL;
                break;
        }
@@ -3208,8 +3258,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
                return -ENOTSUPP;
 
-       dev_dbg(priv->adapter->dev,
-               "TDLS peer=%pM, oper=%d\n", peer, action);
+       mwifiex_dbg(priv->adapter, MSG,
+                   "TDLS peer=%pM, oper=%d\n", peer, action);
 
        switch (action) {
        case NL80211_TDLS_ENABLE_LINK:
@@ -3220,22 +3270,22 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
                break;
        case NL80211_TDLS_TEARDOWN:
                /* shouldn't happen!*/
-               dev_warn(priv->adapter->dev,
-                        "tdls_oper: teardown from driver not supported\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: teardown from driver not supported\n");
                return -EINVAL;
        case NL80211_TDLS_SETUP:
                /* shouldn't happen!*/
-               dev_warn(priv->adapter->dev,
-                        "tdls_oper: setup from driver not supported\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: setup from driver not supported\n");
                return -EINVAL;
        case NL80211_TDLS_DISCOVERY_REQ:
                /* shouldn't happen!*/
-               dev_warn(priv->adapter->dev,
-                        "tdls_oper: discovery from driver not supported\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: discovery from driver not supported\n");
                return -EINVAL;
        default:
-               dev_err(priv->adapter->dev,
-                       "tdls_oper: operation not supported\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls_oper: operation not supported\n");
                return -ENOTSUPP;
        }
 
@@ -3268,8 +3318,8 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
        if (priv->adapter->scan_processing) {
-               dev_err(priv->adapter->dev,
-                       "radar detection: scan in process...\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "radar detection: scan in process...\n");
                return -EBUSY;
        }
 
@@ -3284,8 +3334,8 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                                           params->beacon_csa.tail,
                                           params->beacon_csa.tail_len);
        if (!chsw_ie) {
-               dev_err(priv->adapter->dev,
-                       "Could not parse channel switch announcement IE\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Could not parse channel switch announcement IE\n");
                return -EINVAL;
        }
 
@@ -3297,10 +3347,12 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        }
 
        if (mwifiex_del_mgmt_ies(priv))
-               wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to delete mgmt IEs!\n");
 
        if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
-               wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: setting mgmt ies failed\n", __func__);
                return -EFAULT;
        }
 
@@ -3324,16 +3376,17 @@ mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
        struct mwifiex_radar_params radar_params;
 
        if (priv->adapter->scan_processing) {
-               dev_err(priv->adapter->dev,
-                       "radar detection: scan already in process...\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "radar detection: scan already in process...\n");
                return -EBUSY;
        }
 
        if (!mwifiex_is_11h_active(priv)) {
-               dev_dbg(priv->adapter->dev, "Enable 11h extensions in FW\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Enable 11h extensions in FW\n");
                if (mwifiex_11h_activate(priv, true)) {
-                       dev_err(priv->adapter->dev,
-                               "Failed to activate 11h extensions!!");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to activate 11h extensions!!");
                        return -1;
                }
                priv->state_11h.is_11h_active = true;
@@ -3492,7 +3545,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
        wiphy = wiphy_new(&mwifiex_cfg80211_ops,
                          sizeof(struct mwifiex_adapter *));
        if (!wiphy) {
-               dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: creating new wiphy\n", __func__);
                return -ENOMEM;
        }
        wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
@@ -3563,20 +3617,22 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 
        ret = wiphy_register(wiphy);
        if (ret < 0) {
-               dev_err(adapter->dev,
-                       "%s: wiphy_register failed: %d\n", __func__, ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: wiphy_register failed: %d\n", __func__, ret);
                wiphy_free(wiphy);
                return ret;
        }
 
        if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
-               wiphy_info(wiphy, "driver hint alpha2: %2.2s\n", reg_alpha2);
+               mwifiex_dbg(adapter, INFO,
+                           "driver hint alpha2: %2.2s\n", reg_alpha2);
                regulatory_hint(wiphy, reg_alpha2);
        } else {
                country_code = mwifiex_11d_code_2_region(adapter->region_code);
                if (country_code)
-                       wiphy_info(wiphy, "ignoring F/W country code %2.2s\n",
-                                  country_code);
+                       mwifiex_dbg(adapter, WARN,
+                                   "ignoring F/W country code %2.2s\n",
+                                   country_code);
        }
 
        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
index e9df8826f12412b9d70d432146688bd80bf6fedc..3ddb8ec676ed3df00a7dbdb7880cd23e9844bc97 100644 (file)
@@ -327,8 +327,9 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
                sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ];
 
        if (!sband) {
-               dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n",
-                       __func__, band);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot find cfp by band %d\n",
+                           __func__, band);
                return cfp;
        }
 
@@ -349,9 +350,10 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
                }
        }
        if (i == sband->n_channels) {
-               dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
-                       " & channel=%d freq=%d\n", __func__, band, channel,
-                       freq);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot find cfp by band %d\t"
+                           "& channel=%d freq=%d\n",
+                           __func__, band, channel, freq);
        } else {
                if (!ch)
                        return cfp;
@@ -431,15 +433,17 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
            priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
                switch (adapter->config_bands) {
                case BAND_B:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_b\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_b\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_b,
                                               sizeof(supported_rates_b));
                        break;
                case BAND_G:
                case BAND_G | BAND_GN:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_g\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_g\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_g,
                                               sizeof(supported_rates_g));
                        break;
@@ -449,15 +453,17 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
                case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
                case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
                case BAND_B | BAND_G | BAND_GN:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_bg\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_bg\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_bg,
                                               sizeof(supported_rates_bg));
                        break;
                case BAND_A:
                case BAND_A | BAND_G:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_a\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_a\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_a,
                                               sizeof(supported_rates_a));
                        break;
@@ -466,14 +472,16 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
                case BAND_A | BAND_AN | BAND_AAC:
                case BAND_A | BAND_G | BAND_AN | BAND_GN:
                case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_a\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_a\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_a,
                                               sizeof(supported_rates_a));
                        break;
                case BAND_GN:
-                       dev_dbg(adapter->dev, "info: infra band=%d "
-                               "supported_rates_n\n", adapter->config_bands);
+                       mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
+                                   "supported_rates_n\n",
+                                   adapter->config_bands);
                        k = mwifiex_copy_rates(rates, k, supported_rates_n,
                                               sizeof(supported_rates_n));
                        break;
@@ -482,25 +490,25 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
                /* Ad-hoc mode */
                switch (adapter->adhoc_start_band) {
                case BAND_B:
-                       dev_dbg(adapter->dev, "info: adhoc B\n");
+                       mwifiex_dbg(adapter, INFO, "info: adhoc B\n");
                        k = mwifiex_copy_rates(rates, k, adhoc_rates_b,
                                               sizeof(adhoc_rates_b));
                        break;
                case BAND_G:
                case BAND_G | BAND_GN:
-                       dev_dbg(adapter->dev, "info: adhoc G only\n");
+                       mwifiex_dbg(adapter, INFO, "info: adhoc G only\n");
                        k = mwifiex_copy_rates(rates, k, adhoc_rates_g,
                                               sizeof(adhoc_rates_g));
                        break;
                case BAND_B | BAND_G:
                case BAND_B | BAND_G | BAND_GN:
-                       dev_dbg(adapter->dev, "info: adhoc BG\n");
+                       mwifiex_dbg(adapter, INFO, "info: adhoc BG\n");
                        k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,
                                               sizeof(adhoc_rates_bg));
                        break;
                case BAND_A:
                case BAND_A | BAND_AN:
-                       dev_dbg(adapter->dev, "info: adhoc A\n");
+                       mwifiex_dbg(adapter, INFO, "info: adhoc A\n");
                        k = mwifiex_copy_rates(rates, k, adhoc_rates_a,
                                               sizeof(adhoc_rates_a));
                        break;
index c5a14ff7eb82d63dc5a4e1560ff33acfe2cebaac..a1de83fd1dbe4a0c2f535844ef6978fd256d5cea 100644 (file)
@@ -62,7 +62,8 @@ mwifiex_get_cmd_node(struct mwifiex_adapter *adapter)
 
        spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
        if (list_empty(&adapter->cmd_free_q)) {
-               dev_err(adapter->dev, "GET_CMD_NODE: cmd node not available\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "GET_CMD_NODE: cmd node not available\n");
                spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
                return NULL;
        }
@@ -116,7 +117,8 @@ static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
 {
        /* Copy the HOST command to command buffer */
        memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
-       dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: host cmd size = %d\n", pcmd_ptr->len);
        return 0;
 }
 
@@ -147,8 +149,9 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
 
        /* Sanity test */
        if (host_cmd == NULL || host_cmd->size == 0) {
-               dev_err(adapter->dev, "DNLD_CMD: host_cmd is null"
-                       " or cmd size is 0, not sending\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: host_cmd is null\t"
+                           "or cmd size is 0, not sending\n");
                if (cmd_node->wait_q_enabled)
                        adapter->cmd_wait_q.status = -1;
                mwifiex_recycle_cmd_node(adapter, cmd_node);
@@ -161,8 +164,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
            cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
            cmd_code != HostCmd_CMD_FUNC_INIT) {
-               dev_err(adapter->dev,
-                       "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
                        cmd_code);
                if (cmd_node->wait_q_enabled)
                        mwifiex_complete_cmd(adapter, cmd_node);
@@ -197,10 +200,12 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
                 */
                skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
 
-       dev_dbg(adapter->dev,
-               "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code,
-               le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
-               le16_to_cpu(host_cmd->seq_num));
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+                   cmd_code,
+                   le16_to_cpu(*(__le16 *)((u8 *)host_cmd + S_DS_GEN)),
+                   cmd_size, le16_to_cpu(host_cmd->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size);
 
        if (adapter->iface_type == MWIFIEX_USB) {
                tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
@@ -221,7 +226,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        }
 
        if (ret == -1) {
-               dev_err(adapter->dev, "DNLD_CMD: host to card failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "DNLD_CMD: host to card failed\n");
                if (adapter->iface_type == MWIFIEX_USB)
                        adapter->cmd_sent = false;
                if (cmd_node->wait_q_enabled)
@@ -280,12 +286,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
                                        (adapter->seq_num, priv->bss_num,
                                         priv->bss_type)));
 
-       dev_dbg(adapter->dev,
-               "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
                le16_to_cpu(sleep_cfm_buf->command),
                le16_to_cpu(sleep_cfm_buf->action),
                le16_to_cpu(sleep_cfm_buf->size),
                le16_to_cpu(sleep_cfm_buf->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf,
+                        le16_to_cpu(sleep_cfm_buf->size));
 
        if (adapter->iface_type == MWIFIEX_USB) {
                sleep_cfm_tmp =
@@ -311,7 +319,7 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
        }
 
        if (ret == -1) {
-               dev_err(adapter->dev, "SLEEP_CFM: failed\n");
+               mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n");
                adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
                return -1;
        }
@@ -362,8 +370,9 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter)
        for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
                cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
                if (!cmd_array[i].skb) {
-                       dev_err(adapter->dev, "ALLOC_CMD_BUF: out of memory\n");
-                       return -1;
+                       mwifiex_dbg(adapter, ERROR,
+                                   "unable to allocate command buffer\n");
+                       return -ENOMEM;
                }
        }
 
@@ -386,7 +395,8 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
 
        /* Need to check if cmd pool is allocated or not */
        if (!adapter->cmd_pool) {
-               dev_dbg(adapter->dev, "info: FREE_CMD_BUF: cmd_pool is null\n");
+               mwifiex_dbg(adapter, FATAL,
+                           "info: FREE_CMD_BUF: cmd_pool is null\n");
                return 0;
        }
 
@@ -395,7 +405,8 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
        /* Release shared memory buffers */
        for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
                if (cmd_array[i].skb) {
-                       dev_dbg(adapter->dev, "cmd: free cmd buffer %d\n", i);
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: free cmd buffer %d\n", i);
                        dev_kfree_skb_any(cmd_array[i].skb);
                }
                if (!cmd_array[i].resp_skb)
@@ -409,7 +420,8 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
        }
        /* Release struct cmd_ctrl_node */
        if (adapter->cmd_pool) {
-               dev_dbg(adapter->dev, "cmd: free cmd pool\n");
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: free cmd pool\n");
                kfree(adapter->cmd_pool);
                adapter->cmd_pool = NULL;
        }
@@ -459,7 +471,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
                rx_info->bss_type = priv->bss_type;
        }
 
-       dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause);
+       mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
+       mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", skb->data, skb->len);
 
        if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
                ret = mwifiex_process_uap_event(priv);
@@ -498,28 +511,33 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
        }
 
        if (adapter->is_suspended) {
-               dev_err(adapter->dev, "PREP_CMD: device in suspended state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: device in suspended state\n");
                return -1;
        }
 
        if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
-               dev_err(adapter->dev, "PREP_CMD: host entering sleep state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: host entering sleep state\n");
                return -1;
        }
 
        if (adapter->surprise_removed) {
-               dev_err(adapter->dev, "PREP_CMD: card is removed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: card is removed\n");
                return -1;
        }
 
        if (adapter->is_cmd_timedout) {
-               dev_err(adapter->dev, "PREP_CMD: FW is in bad state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: FW is in bad state\n");
                return -1;
        }
 
        if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) {
                if (cmd_no != HostCmd_CMD_FUNC_INIT) {
-                       dev_err(adapter->dev, "PREP_CMD: FW in reset state\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "PREP_CMD: FW in reset state\n");
                        return -1;
                }
        }
@@ -528,7 +546,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
        cmd_node = mwifiex_get_cmd_node(adapter);
 
        if (!cmd_node) {
-               dev_err(adapter->dev, "PREP_CMD: no free cmd node\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: no free cmd node\n");
                return -1;
        }
 
@@ -536,7 +555,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
        mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync);
 
        if (!cmd_node->cmd_skb) {
-               dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: no free cmd buf\n");
                return -1;
        }
 
@@ -571,7 +591,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
 
        /* Return error, since the command preparation failed */
        if (ret) {
-               dev_err(adapter->dev, "PREP_CMD: cmd %#x preparation failed\n",
+               mwifiex_dbg(adapter, ERROR,
+                           "PREP_CMD: cmd %#x preparation failed\n",
                        cmd_no);
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
                return -1;
@@ -626,7 +647,8 @@ void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
        mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
 
        atomic_dec(&adapter->cmd_pending);
-       dev_dbg(adapter->dev, "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
                le16_to_cpu(host_cmd->command),
                atomic_read(&adapter->cmd_pending));
 }
@@ -648,7 +670,7 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
 
        host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
        if (!host_cmd) {
-               dev_err(adapter->dev, "QUEUE_CMD: host_cmd is NULL\n");
+               mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n");
                return;
        }
 
@@ -673,7 +695,8 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
        spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 
        atomic_inc(&adapter->cmd_pending);
-       dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
                command, atomic_read(&adapter->cmd_pending));
 }
 
@@ -699,7 +722,8 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
 
        /* Check if already in processing */
        if (adapter->curr_cmd) {
-               dev_err(adapter->dev, "EXEC_NEXT_CMD: cmd in processing\n");
+               mwifiex_dbg(adapter, FATAL,
+                           "EXEC_NEXT_CMD: cmd in processing\n");
                return -1;
        }
 
@@ -721,8 +745,9 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
        priv = cmd_node->priv;
 
        if (adapter->ps_state != PS_STATE_AWAKE) {
-               dev_err(adapter->dev, "%s: cannot send cmd in sleep state,"
-                               " this should not happen\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: cannot send cmd in sleep state,\t"
+                           "this should not happen\n", __func__);
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
                return ret;
        }
@@ -772,8 +797,9 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 
        if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
                resp = (struct host_cmd_ds_command *) adapter->upld_buf;
-               dev_err(adapter->dev, "CMD_RESP: NULL curr_cmd, %#x\n",
-                       le16_to_cpu(resp->command));
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: NULL curr_cmd, %#x\n",
+                           le16_to_cpu(resp->command));
                return -1;
        }
 
@@ -781,8 +807,9 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 
        resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
        if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
-               dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n",
-                       le16_to_cpu(resp->command));
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: %#x been canceled\n",
+                           le16_to_cpu(resp->command));
                mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
                adapter->curr_cmd = NULL;
@@ -794,7 +821,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
                /* Copy original response back to response buffer */
                struct mwifiex_ds_misc_cmd *hostcmd;
                uint16_t size = le16_to_cpu(resp->size);
-               dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
+               mwifiex_dbg(adapter, INFO,
+                           "info: host cmd resp size = %d\n", size);
                size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
                if (adapter->curr_cmd->data_buf) {
                        hostcmd = adapter->curr_cmd->data_buf;
@@ -822,13 +850,15 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
        adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
                                                                orig_cmdresp_no;
 
-       dev_dbg(adapter->dev,
-               "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
-               orig_cmdresp_no, cmdresp_result,
-               le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+                   orig_cmdresp_no, cmdresp_result,
+                   le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
+       mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp,
+                        le16_to_cpu(resp->size));
 
        if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
-               dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
+               mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n");
                if (adapter->curr_cmd->wait_q_enabled)
                        adapter->cmd_wait_q.status = -1;
 
@@ -852,8 +882,9 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
        /* Check init command response */
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
                if (ret) {
-                       dev_err(adapter->dev, "%s: cmd %#x failed during "
-                               "initialization\n", __func__, cmdresp_no);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: cmd %#x failed during\t"
+                                   "initialization\n", __func__, cmdresp_no);
                        mwifiex_init_fw_complete(adapter);
                        return -1;
                } else if (adapter->last_init_cmd == cmdresp_no)
@@ -888,7 +919,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
        adapter->is_cmd_timedout = 1;
        if (!adapter->curr_cmd) {
-               dev_dbg(adapter->dev, "cmd: empty curr_cmd\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd: empty curr_cmd\n");
                return;
        }
        cmd_node = adapter->curr_cmd;
@@ -897,47 +929,60 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
                        adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
                adapter->dbg.timeout_cmd_act =
                        adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
-               dev_err(adapter->dev,
-                       "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
-                       adapter->dbg.timeout_cmd_id,
-                       adapter->dbg.timeout_cmd_act);
-
-               dev_err(adapter->dev, "num_data_h2c_failure = %d\n",
-                       adapter->dbg.num_tx_host_to_card_failure);
-               dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n",
-                       adapter->dbg.num_cmd_host_to_card_failure);
-
-               dev_err(adapter->dev, "is_cmd_timedout = %d\n",
-                       adapter->is_cmd_timedout);
-               dev_err(adapter->dev, "num_tx_timeout = %d\n",
-                       adapter->dbg.num_tx_timeout);
-
-               dev_err(adapter->dev, "last_cmd_index = %d\n",
-                       adapter->dbg.last_cmd_index);
-               dev_err(adapter->dev, "last_cmd_id: %*ph\n",
-                       (int)sizeof(adapter->dbg.last_cmd_id),
-                       adapter->dbg.last_cmd_id);
-               dev_err(adapter->dev, "last_cmd_act: %*ph\n",
-                       (int)sizeof(adapter->dbg.last_cmd_act),
-                       adapter->dbg.last_cmd_act);
-
-               dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
-                       adapter->dbg.last_cmd_resp_index);
-               dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
-                       (int)sizeof(adapter->dbg.last_cmd_resp_id),
-                       adapter->dbg.last_cmd_resp_id);
-
-               dev_err(adapter->dev, "last_event_index = %d\n",
-                       adapter->dbg.last_event_index);
-               dev_err(adapter->dev, "last_event: %*ph\n",
-                       (int)sizeof(adapter->dbg.last_event),
-                       adapter->dbg.last_event);
-
-               dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
-                       adapter->data_sent, adapter->cmd_sent);
-
-               dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
-                       adapter->ps_mode, adapter->ps_state);
+               mwifiex_dbg(adapter, MSG,
+                           "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
+                           adapter->dbg.timeout_cmd_id,
+                           adapter->dbg.timeout_cmd_act);
+
+               mwifiex_dbg(adapter, MSG,
+                           "num_data_h2c_failure = %d\n",
+                           adapter->dbg.num_tx_host_to_card_failure);
+               mwifiex_dbg(adapter, MSG,
+                           "num_cmd_h2c_failure = %d\n",
+                           adapter->dbg.num_cmd_host_to_card_failure);
+
+               mwifiex_dbg(adapter, MSG,
+                           "is_cmd_timedout = %d\n",
+                           adapter->is_cmd_timedout);
+               mwifiex_dbg(adapter, MSG,
+                           "num_tx_timeout = %d\n",
+                           adapter->dbg.num_tx_timeout);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_index = %d\n",
+                           adapter->dbg.last_cmd_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_id: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_id),
+                           adapter->dbg.last_cmd_id);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_act: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_act),
+                           adapter->dbg.last_cmd_act);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_resp_index = %d\n",
+                           adapter->dbg.last_cmd_resp_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_cmd_resp_id: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_cmd_resp_id),
+                           adapter->dbg.last_cmd_resp_id);
+
+               mwifiex_dbg(adapter, MSG,
+                           "last_event_index = %d\n",
+                           adapter->dbg.last_event_index);
+               mwifiex_dbg(adapter, MSG,
+                           "last_event: %*ph\n",
+                           (int)sizeof(adapter->dbg.last_event),
+                           adapter->dbg.last_event);
+
+               mwifiex_dbg(adapter, MSG,
+                           "data_sent=%d cmd_sent=%d\n",
+                           adapter->data_sent, adapter->cmd_sent);
+
+               mwifiex_dbg(adapter, MSG,
+                           "ps_mode=%d ps_state=%d\n",
+                           adapter->ps_mode, adapter->ps_state);
 
                if (cmd_node->wait_q_enabled) {
                        adapter->cmd_wait_q.status = -ETIMEDOUT;
@@ -948,8 +993,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
                mwifiex_init_fw_complete(adapter);
 
-       if (adapter->if_ops.fw_dump)
-               adapter->if_ops.fw_dump(adapter);
+       if (adapter->if_ops.device_dump)
+               adapter->if_ops.device_dump(adapter);
 
        if (adapter->if_ops.card_reset)
                adapter->if_ops.card_reset(adapter);
@@ -1015,7 +1060,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
                        if (!priv)
                                continue;
                        if (priv->scan_request) {
-                               dev_dbg(adapter->dev, "info: aborting scan\n");
+                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
                                cfg80211_scan_done(priv->scan_request, 1);
                                priv->scan_request = NULL;
                        }
@@ -1075,7 +1120,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
                        if (!priv)
                                continue;
                        if (priv->scan_request) {
-                               dev_dbg(adapter->dev, "info: aborting scan\n");
+                               mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
                                cfg80211_scan_done(priv->scan_request, 1);
                                priv->scan_request = NULL;
                        }
@@ -1100,11 +1145,11 @@ mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
            !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
                mwifiex_dnld_sleep_confirm_cmd(adapter);
        else
-               dev_dbg(adapter->dev,
-                       "cmd: Delay Sleep Confirm (%s%s%s)\n",
-                       (adapter->cmd_sent) ? "D" : "",
-                       (adapter->curr_cmd) ? "C" : "",
-                       (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: Delay Sleep Confirm (%s%s%s)\n",
+                           (adapter->cmd_sent) ? "D" : "",
+                           (adapter->curr_cmd) ? "C" : "",
+                           (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
 }
 
 /*
@@ -1120,15 +1165,18 @@ mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated)
                        priv->adapter->hs_activated = true;
                        mwifiex_update_rxreor_flags(priv->adapter,
                                                    RXREOR_FORCE_NO_DROP);
-                       dev_dbg(priv->adapter->dev, "event: hs_activated\n");
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: hs_activated\n");
                        priv->adapter->hs_activate_wait_q_woken = true;
                        wake_up_interruptible(
                                &priv->adapter->hs_activate_wait_q);
                } else {
-                       dev_dbg(priv->adapter->dev, "event: HS not configured\n");
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "event: HS not configured\n");
                }
        } else {
-               dev_dbg(priv->adapter->dev, "event: hs_deactivated\n");
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "event: hs_deactivated\n");
                priv->adapter->hs_activated = false;
        }
 }
@@ -1156,11 +1204,12 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
                mwifiex_hs_activated_event(priv, true);
                return 0;
        } else {
-               dev_dbg(adapter->dev, "cmd: CMD_RESP: HS_CFG cmd reply"
-                       " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
-                       resp->result, conditions,
-                       phs_cfg->params.hs_config.gpio,
-                       phs_cfg->params.hs_config.gap);
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: CMD_RESP: HS_CFG cmd reply\t"
+                           " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
+                           resp->result, conditions,
+                           phs_cfg->params.hs_config.gpio,
+                           phs_cfg->params.hs_config.gap);
        }
        if (conditions != HS_CFG_CANCEL) {
                adapter->is_hs_configured = true;
@@ -1182,8 +1231,10 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
 void
 mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "info: %s: auto cancelling host sleep"
-               " since there is interrupt from the firmware\n", __func__);
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: auto cancelling host sleep\t"
+                   "since there is interrupt from the firmware\n",
+                   __func__);
 
        adapter->if_ops.wakeup(adapter);
        adapter->hs_activated = false;
@@ -1212,13 +1263,14 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
        uint16_t seq_num = le16_to_cpu(cmd->seq_num);
 
        if (!upld_len) {
-               dev_err(adapter->dev, "%s: cmd size is 0\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: cmd size is 0\n", __func__);
                return;
        }
 
-       dev_dbg(adapter->dev,
-               "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
-               command, result, le16_to_cpu(cmd->size), seq_num);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+                   command, result, le16_to_cpu(cmd->size), seq_num);
 
        /* Get BSS number and corresponding priv */
        priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
@@ -1232,15 +1284,16 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
        command &= HostCmd_CMD_ID_MASK;
 
        if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
-               dev_err(adapter->dev,
-                       "%s: rcvd unexpected resp for cmd %#x, result = %x\n",
-                       __func__, command, result);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: rcvd unexpected resp for cmd %#x, result = %x\n",
+                           __func__, command, result);
                return;
        }
 
        if (result) {
-               dev_err(adapter->dev, "%s: sleep confirm cmd failed\n",
-                       __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: sleep confirm cmd failed\n",
+                           __func__);
                adapter->pm_wakeup_card_req = false;
                adapter->ps_state = PS_STATE_AWAKE;
                return;
@@ -1305,7 +1358,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
                                        sizeof(struct mwifiex_ie_types_header));
                        cmd_size += sizeof(*ps_tlv);
                        tlv += sizeof(*ps_tlv);
-                       dev_dbg(adapter->dev, "cmd: PS Command: Enter PS\n");
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "cmd: PS Command: Enter PS\n");
                        ps_mode->null_pkt_interval =
                                        cpu_to_le16(adapter->null_pkt_interval);
                        ps_mode->multiple_dtims =
@@ -1335,8 +1389,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
                        tlv += sizeof(*auto_ds_tlv);
                        if (auto_ds)
                                idletime = auto_ds->idle_time;
-                       dev_dbg(priv->adapter->dev,
-                               "cmd: PS Command: Enter Auto Deep Sleep\n");
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "cmd: PS Command: Enter Auto Deep Sleep\n");
                        auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
                }
                cmd->size = cpu_to_le16(cmd_size);
@@ -1363,27 +1417,31 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
        uint16_t auto_ps_bitmap =
                le16_to_cpu(ps_mode->params.ps_bitmap);
 
-       dev_dbg(adapter->dev,
-               "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
-               __func__, resp->result, action);
+       mwifiex_dbg(adapter, INFO,
+                   "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
+                   __func__, resp->result, action);
        if (action == EN_AUTO_PS) {
                if (auto_ps_bitmap & BITMAP_AUTO_DS) {
-                       dev_dbg(adapter->dev, "cmd: Enabled auto deep sleep\n");
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Enabled auto deep sleep\n");
                        priv->adapter->is_deep_sleep = true;
                }
                if (auto_ps_bitmap & BITMAP_STA_PS) {
-                       dev_dbg(adapter->dev, "cmd: Enabled STA power save\n");
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Enabled STA power save\n");
                        if (adapter->sleep_period.period)
-                               dev_dbg(adapter->dev,
-                                       "cmd: set to uapsd/pps mode\n");
+                               mwifiex_dbg(adapter, CMD,
+                                           "cmd: set to uapsd/pps mode\n");
                }
        } else if (action == DIS_AUTO_PS) {
                if (ps_bitmap & BITMAP_AUTO_DS) {
                        priv->adapter->is_deep_sleep = false;
-                       dev_dbg(adapter->dev, "cmd: Disabled auto deep sleep\n");
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Disabled auto deep sleep\n");
                }
                if (ps_bitmap & BITMAP_STA_PS) {
-                       dev_dbg(adapter->dev, "cmd: Disabled STA power save\n");
+                       mwifiex_dbg(adapter, CMD,
+                                   "cmd: Disabled STA power save\n");
                        if (adapter->sleep_period.period) {
                                adapter->delay_null_pkt = false;
                                adapter->tx_lock_flag = false;
@@ -1396,7 +1454,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
                else
                        adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
 
-               dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: ps_bitmap=%#x\n", ps_bitmap);
 
                if (pm_cfg) {
                        /* This section is for get power save mode */
@@ -1533,29 +1592,29 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
                                                        api_rev->major_ver;
                                        adapter->key_api_minor_ver =
                                                        api_rev->minor_ver;
-                                       dev_dbg(adapter->dev,
-                                               "key_api v%d.%d\n",
-                                               adapter->key_api_major_ver,
-                                               adapter->key_api_minor_ver);
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "key_api v%d.%d\n",
+                                                   adapter->key_api_major_ver,
+                                                   adapter->key_api_minor_ver);
                                        break;
                                case FW_API_VER_ID:
                                        adapter->fw_api_ver =
                                                        api_rev->major_ver;
-                                       dev_dbg(adapter->dev,
-                                               "Firmware api version %d\n",
-                                               adapter->fw_api_ver);
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "Firmware api version %d\n",
+                                                   adapter->fw_api_ver);
                                        break;
                                default:
-                                       dev_warn(adapter->dev,
-                                                "Unknown api_id: %d\n",
-                                                api_id);
+                                       mwifiex_dbg(adapter, FATAL,
+                                                   "Unknown api_id: %d\n",
+                                                   api_id);
                                        break;
                                }
                                break;
                        default:
-                               dev_warn(adapter->dev,
-                                        "Unknown GET_HW_SPEC TLV type: %#x\n",
-                                        le16_to_cpu(tlv->type));
+                               mwifiex_dbg(adapter, FATAL,
+                                           "Unknown GET_HW_SPEC TLV type: %#x\n",
+                                           le16_to_cpu(tlv->type));
                                break;
                        }
                        parsed_len += le16_to_cpu(tlv->len) +
@@ -1565,14 +1624,16 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
                }
        }
 
-       dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n",
-               adapter->fw_release_number);
-       dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n",
-               hw_spec->permanent_addr);
-       dev_dbg(adapter->dev,
-               "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
-               le16_to_cpu(hw_spec->hw_if_version),
-               le16_to_cpu(hw_spec->version));
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: fw_release_number- %#x\n",
+                   adapter->fw_release_number);
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: permanent addr: %pM\n",
+                   hw_spec->permanent_addr);
+       mwifiex_dbg(adapter, INFO,
+                   "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
+                   le16_to_cpu(hw_spec->hw_if_version),
+                   le16_to_cpu(hw_spec->version));
 
        ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
        adapter->region_code = le16_to_cpu(hw_spec->region_code);
@@ -1585,8 +1646,8 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
        /* If it's unidentified region code, use the default (USA) */
        if (i >= MWIFIEX_MAX_REGION_CODE) {
                adapter->region_code = 0x10;
-               dev_dbg(adapter->dev,
-                       "cmd: unknown region code, use default (USA)\n");
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: unknown region code, use default (USA)\n");
        }
 
        adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
index 1fb329dc6744580c6834f03a52d2f71424db8392..5a0636d43a1b9722b4be1e95b7528aa0ae6368f9 100644 (file)
@@ -152,24 +152,24 @@ free_and_exit:
 }
 
 /*
- * Proc firmware dump read handler.
+ * Proc device dump read handler.
  *
- * This function is called when the 'fw_dump' file is opened for
+ * This function is called when the 'device_dump' file is opened for
  * reading.
- * This function dumps firmware memory in different files
- * (ex. DTCM, ITCM, SQRAM etc.) based on the the segments for
+ * This function dumps driver information and firmware memory segments
+ * (ex. DTCM, ITCM, SQRAM etc.) for
  * debugging.
  */
 static ssize_t
-mwifiex_fw_dump_read(struct file *file, char __user *ubuf,
-                    size_t count, loff_t *ppos)
+mwifiex_device_dump_read(struct file *file, char __user *ubuf,
+                        size_t count, loff_t *ppos)
 {
        struct mwifiex_private *priv = file->private_data;
 
-       if (!priv->adapter->if_ops.fw_dump)
+       if (!priv->adapter->if_ops.device_dump)
                return -EIO;
 
-       priv->adapter->if_ops.fw_dump(priv->adapter);
+       priv->adapter->if_ops.device_dump(priv->adapter);
 
        return 0;
 }
@@ -535,6 +535,144 @@ done:
        return ret;
 }
 
+/* Proc debug_mask file read handler.
+ * This function is called when the 'debug_mask' file is opened for reading
+ * This function can be used read driver debugging mask value.
+ */
+static ssize_t
+mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
+                       size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv =
+               (struct mwifiex_private *)file->private_data;
+       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)page;
+       size_t ret = 0;
+       int pos = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
+                       priv->adapter->debug_mask);
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+       free_page(page);
+       return ret;
+}
+
+/* Proc debug_mask file read handler.
+ * This function is called when the 'debug_mask' file is opened for reading
+ * This function can be used read driver debugging mask value.
+ */
+static ssize_t
+mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
+                        size_t count, loff_t *ppos)
+{
+       int ret;
+       unsigned long debug_mask;
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (void *)addr;
+       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       if (kstrtoul(buf, 0, &debug_mask)) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       priv->adapter->debug_mask = debug_mask;
+       ret = count;
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc memrw file write handler.
+ * This function is called when the 'memrw' file is opened for writing
+ * This function can be used to write to a memory location.
+ */
+static ssize_t
+mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
+                   loff_t *ppos)
+{
+       int ret;
+       char cmd;
+       struct mwifiex_ds_mem_rw mem_rw;
+       u16 cmd_action;
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (void *)addr;
+       size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
+
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, ubuf, buf_size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
+       if (ret != 3) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if ((cmd == 'r') || (cmd == 'R')) {
+               cmd_action = HostCmd_ACT_GEN_GET;
+               mem_rw.value = 0;
+       } else if ((cmd == 'w') || (cmd == 'W')) {
+               cmd_action = HostCmd_ACT_GEN_SET;
+       } else {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
+                            &mem_rw, true))
+               ret = -1;
+       else
+               ret = count;
+
+done:
+       free_page(addr);
+       return ret;
+}
+
+/* Proc memrw file read handler.
+ * This function is called when the 'memrw' file is opened for reading
+ * This function can be used to read from a memory location.
+ */
+static ssize_t
+mwifiex_memrw_read(struct file *file, char __user *ubuf,
+                  size_t count, loff_t *ppos)
+{
+       struct mwifiex_private *priv = (void *)file->private_data;
+       unsigned long addr = get_zeroed_page(GFP_KERNEL);
+       char *buf = (char *)addr;
+       int ret, pos = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
+                       priv->mem_rw.value);
+       ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+       free_page(addr);
+       return ret;
+}
+
 static u32 saved_offset = -1, saved_bytes = -1;
 
 /*
@@ -654,7 +792,8 @@ mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
        memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
 
        if (arg_num > 3) {
-               dev_err(priv->adapter->dev, "Too many arguments\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Too many arguments\n");
                ret = -EINVAL;
                goto done;
        }
@@ -746,11 +885,13 @@ static const struct file_operations mwifiex_dfs_##name##_fops = {       \
 MWIFIEX_DFS_FILE_READ_OPS(info);
 MWIFIEX_DFS_FILE_READ_OPS(debug);
 MWIFIEX_DFS_FILE_READ_OPS(getlog);
-MWIFIEX_DFS_FILE_READ_OPS(fw_dump);
+MWIFIEX_DFS_FILE_READ_OPS(device_dump);
 MWIFIEX_DFS_FILE_OPS(regrdwr);
 MWIFIEX_DFS_FILE_OPS(rdeeprom);
+MWIFIEX_DFS_FILE_OPS(memrw);
 MWIFIEX_DFS_FILE_OPS(hscfg);
 MWIFIEX_DFS_FILE_OPS(histogram);
+MWIFIEX_DFS_FILE_OPS(debug_mask);
 
 /*
  * This function creates the debug FS directory structure and the files.
@@ -772,9 +913,11 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
        MWIFIEX_DFS_ADD_FILE(getlog);
        MWIFIEX_DFS_ADD_FILE(regrdwr);
        MWIFIEX_DFS_ADD_FILE(rdeeprom);
-       MWIFIEX_DFS_ADD_FILE(fw_dump);
+       MWIFIEX_DFS_ADD_FILE(device_dump);
+       MWIFIEX_DFS_ADD_FILE(memrw);
        MWIFIEX_DFS_ADD_FILE(hscfg);
        MWIFIEX_DFS_ADD_FILE(histogram);
+       MWIFIEX_DFS_ADD_FILE(debug_mask);
 }
 
 /*
index 65d8d6d4b6ba3db2cfa3236e679cfcef6a307905..58400c69ab26adfb7da1fc82f7acf84acfcead2e 100644 (file)
@@ -64,104 +64,7 @@ static int mwifiex_ethtool_set_wol(struct net_device *dev,
        return 0;
 }
 
-static int
-mwifiex_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct memory_type_mapping *entry;
-
-       if (!adapter->if_ops.fw_dump)
-               return -ENOTSUPP;
-
-       dump->flag = adapter->curr_mem_idx;
-       dump->version = 1;
-       if (adapter->curr_mem_idx == MWIFIEX_DRV_INFO_IDX) {
-               dump->len = adapter->drv_info_size;
-       } else if (adapter->curr_mem_idx != MWIFIEX_FW_DUMP_IDX) {
-               entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
-               dump->len = entry->mem_size;
-       } else {
-               dump->len = 0;
-       }
-
-       return 0;
-}
-
-static int
-mwifiex_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
-                     void *buffer)
-{
-       u8 *p = buffer;
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_adapter *adapter = priv->adapter;
-       struct memory_type_mapping *entry;
-
-       if (!adapter->if_ops.fw_dump)
-               return -ENOTSUPP;
-
-       if (adapter->curr_mem_idx == MWIFIEX_DRV_INFO_IDX) {
-               if (!adapter->drv_info_dump)
-                       return -EFAULT;
-               memcpy(p, adapter->drv_info_dump, adapter->drv_info_size);
-               return 0;
-       }
-
-       if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
-               dev_err(adapter->dev, "firmware dump in progress!!\n");
-               return -EBUSY;
-       }
-
-       entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
-
-       if (!entry->mem_ptr)
-               return -EFAULT;
-
-       memcpy(p, entry->mem_ptr, entry->mem_size);
-
-       entry->mem_size = 0;
-       vfree(entry->mem_ptr);
-       entry->mem_ptr = NULL;
-
-       return 0;
-}
-
-static int mwifiex_set_dump(struct net_device *dev, struct ethtool_dump *val)
-{
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       if (!adapter->if_ops.fw_dump)
-               return -ENOTSUPP;
-
-       if (val->flag == MWIFIEX_DRV_INFO_IDX) {
-               adapter->curr_mem_idx = MWIFIEX_DRV_INFO_IDX;
-               return 0;
-       }
-
-       if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
-               dev_err(adapter->dev, "firmware dump in progress!!\n");
-               return -EBUSY;
-       }
-
-       if (val->flag == MWIFIEX_FW_DUMP_IDX) {
-               adapter->curr_mem_idx = val->flag;
-               adapter->if_ops.fw_dump(adapter);
-               return 0;
-       }
-
-       if (val->flag < 0 || val->flag >= adapter->num_mem_types)
-               return -EINVAL;
-
-       adapter->curr_mem_idx = val->flag;
-
-       return 0;
-}
-
 const struct ethtool_ops mwifiex_ethtool_ops = {
        .get_wol = mwifiex_ethtool_get_wol,
        .set_wol = mwifiex_ethtool_set_wol,
-       .get_dump_flag = mwifiex_get_dump_flag,
-       .get_dump_data = mwifiex_get_dump_data,
-       .set_dump = mwifiex_set_dump,
 };
index 59d8964dd0dcaaadc39d0c09f872fe46c5488c4d..c404390cb0fa42b8d7778fcf23c121600ee48811 100644 (file)
@@ -323,6 +323,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT            0x0075
 #define HostCmd_CMD_802_11_TX_RATE_QUERY              0x007f
 #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS     0x0083
+#define HostCmd_CMD_MEM_ACCESS                        0x0086
 #define HostCmd_CMD_CFG_DATA                          0x008f
 #define HostCmd_CMD_VERSION_EXT                       0x0097
 #define HostCmd_CMD_MEF_CFG                           0x009a
@@ -1576,6 +1577,13 @@ struct mwifiex_ie_types_extcap {
        u8 ext_capab[0];
 } __packed;
 
+struct host_cmd_ds_mem_access {
+       __le16 action;
+       __le16 reserved;
+       __le32 addr;
+       __le32 value;
+};
+
 struct mwifiex_ie_types_qos_info {
        struct mwifiex_ie_types_header header;
        u8 qos_info;
@@ -1958,6 +1966,7 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_p2p_mode_cfg mode_cfg;
                struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
                struct host_cmd_ds_mef_cfg mef_cfg;
+               struct host_cmd_ds_mem_access mem;
                struct host_cmd_ds_mac_reg_access mac_reg;
                struct host_cmd_ds_bbp_reg_access bbp_reg;
                struct host_cmd_ds_rf_reg_access rf_reg;
index e12192f5cfad306b8cd9d4e5fce7ec2bd2e67957..df7fdc09d38c7f1e326b59ad8fd0a9ea53485f74 100644 (file)
@@ -56,7 +56,7 @@ static void wakeup_timer_fn(unsigned long data)
 {
        struct mwifiex_adapter *adapter = (struct mwifiex_adapter *)data;
 
-       dev_err(adapter->dev, "Firmware wakeup failed\n");
+       mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n");
        adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
        mwifiex_cancel_all_pending_cmd(adapter);
 
@@ -172,8 +172,9 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
        /* Allocate command buffer */
        ret = mwifiex_alloc_cmd_buffer(adapter);
        if (ret) {
-               dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n",
-                       __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to alloc cmd buffer\n",
+                           __func__);
                return -1;
        }
 
@@ -182,8 +183,9 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
                              + INTF_HEADER_LEN);
 
        if (!adapter->sleep_cfm) {
-               dev_err(adapter->dev, "%s: failed to alloc sleep cfm"
-                       " cmd buffer\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to alloc sleep cfm\t"
+                           " cmd buffer\n", __func__);
                return -1;
        }
        skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN);
@@ -417,7 +419,7 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
        mwifiex_free_lock_list(adapter);
 
        /* Free command buffer */
-       dev_dbg(adapter->dev, "info: free cmd buffer\n");
+       mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n");
        mwifiex_free_cmd_buffer(adapter);
 
        for (idx = 0; idx < adapter->num_mem_types; idx++) {
@@ -433,6 +435,7 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 
        if (adapter->drv_info_dump) {
                vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
                adapter->drv_info_size = 0;
        }
 
@@ -595,10 +598,11 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
        for (i = 0; i < adapter->priv_num; ++i) {
                head = &adapter->bss_prio_tbl[i].bss_prio_head;
                lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
-               dev_dbg(adapter->dev, "info: delete BSS priority table,"
-                               " bss_type = %d, bss_num = %d, i = %d,"
-                               " head = %p\n",
-                             priv->bss_type, priv->bss_num, i, head);
+               mwifiex_dbg(adapter, INFO,
+                           "info: delete BSS priority table,\t"
+                           "bss_type = %d, bss_num = %d, i = %d,\t"
+                           "head = %p\n",
+                           priv->bss_type, priv->bss_num, i, head);
 
                {
                        spin_lock_irqsave(lock, flags);
@@ -609,9 +613,10 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
                        list_for_each_entry_safe(bssprio_node, tmp_node, head,
                                                 list) {
                                if (bssprio_node->priv == priv) {
-                                       dev_dbg(adapter->dev, "info: Delete "
-                                               "node %p, next = %p\n",
-                                               bssprio_node, tmp_node);
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Delete\t"
+                                                   "node %p, next = %p\n",
+                                                   bssprio_node, tmp_node);
                                        list_del(&bssprio_node->list);
                                        kfree(bssprio_node);
                                }
@@ -659,20 +664,23 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
        adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING;
        /* wait for mwifiex_process to complete */
        if (adapter->mwifiex_processing) {
-               dev_warn(adapter->dev, "main process is still running\n");
+               mwifiex_dbg(adapter, WARN,
+                           "main process is still running\n");
                return ret;
        }
 
        /* cancel current command */
        if (adapter->curr_cmd) {
-               dev_warn(adapter->dev, "curr_cmd is still in processing\n");
+               mwifiex_dbg(adapter, WARN,
+                           "curr_cmd is still in processing\n");
                del_timer_sync(&adapter->cmd_timer);
                mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
                adapter->curr_cmd = NULL;
        }
 
        /* shut down mwifiex */
-       dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
+       mwifiex_dbg(adapter, MSG,
+                   "info: shutdown mwifiex...\n");
 
        /* Clean up Tx/Rx queues and delete BSS priority table */
        for (i = 0; i < adapter->priv_num; i++) {
@@ -741,8 +749,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
                /* check if firmware is already running */
                ret = adapter->if_ops.check_fw_status(adapter, poll_num);
                if (!ret) {
-                       dev_notice(adapter->dev,
-                                  "WLAN FW already running! Skip FW dnld\n");
+                       mwifiex_dbg(adapter, MSG,
+                                   "WLAN FW already running! Skip FW dnld\n");
                        return 0;
                }
 
@@ -750,8 +758,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
 
                /* check if we are the winner for downloading FW */
                if (!adapter->winner) {
-                       dev_notice(adapter->dev,
-                                  "FW already running! Skip FW dnld\n");
+                       mwifiex_dbg(adapter, MSG,
+                                   "FW already running! Skip FW dnld\n");
                        goto poll_fw;
                }
        }
@@ -760,7 +768,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
                /* Download firmware with helper */
                ret = adapter->if_ops.prog_fw(adapter, pmfw);
                if (ret) {
-                       dev_err(adapter->dev, "prog_fw failed ret=%#x\n", ret);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "prog_fw failed ret=%#x\n", ret);
                        return ret;
                }
        }
@@ -769,7 +778,8 @@ poll_fw:
        /* Check if the firmware is downloaded successfully or not */
        ret = adapter->if_ops.check_fw_status(adapter, poll_num);
        if (ret)
-               dev_err(adapter->dev, "FW failed to be active in time\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "FW failed to be active in time\n");
 
        return ret;
 }
index d2b05c3a96da8d81060f4c698020890faab5454a..6f11a25a6b49d86498303f7a4647053eb8c22123 100644 (file)
@@ -189,6 +189,7 @@ struct tdls_peer_info {
 };
 
 struct mwifiex_debug_info {
+       unsigned int debug_mask;
        u32 int_counter;
        u32 packets_out[MAX_NUM_TID];
        u32 tx_buf_size;
@@ -342,6 +343,11 @@ struct mwifiex_ds_read_eeprom {
        u8 value[MAX_EEPROM_DATA];
 };
 
+struct mwifiex_ds_mem_rw {
+       u32 addr;
+       u32 value;
+};
+
 #define IEEE_MAX_IE_SIZE               256
 
 #define MWIFIEX_IE_HDR_SIZE    (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
index 2ee48e7067bfc6b4a7bb596a589811a692d7f9bc..cce8e39aa45e456e66dad6d4f762f07c96b9c9d2 100644 (file)
@@ -53,9 +53,9 @@ mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer)
         *   parameter buffer pointer.
         */
        if (priv->gen_ie_buf_len) {
-               dev_dbg(priv->adapter->dev,
-                       "info: %s: append generic ie len %d to %p\n",
-                       __func__, priv->gen_ie_buf_len, *buffer);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: append generic ie len %d to %p\n",
+                           __func__, priv->gen_ie_buf_len, *buffer);
 
                /* Wrap the generic IE buffer with a pass through TLV type */
                ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
@@ -125,9 +125,9 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer,
 
        tsf_val = cpu_to_le64(bss_desc->timestamp);
 
-       dev_dbg(priv->adapter->dev,
-               "info: %s: TSF offset calc: %016llx - %016llx\n",
-               __func__, bss_desc->timestamp, bss_desc->fw_tsf);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: %s: TSF offset calc: %016llx - %016llx\n",
+                   __func__, bss_desc->timestamp, bss_desc->fw_tsf);
 
        memcpy(*buffer, &tsf_val, sizeof(tsf_val));
        *buffer += sizeof(tsf_val);
@@ -152,7 +152,7 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
 
        tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
        if (!tmp) {
-               dev_err(priv->adapter->dev, "failed to alloc tmp buf\n");
+               mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n");
                return -ENOMEM;
        }
 
@@ -169,8 +169,8 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
                }
        }
 
-       dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n",
-               priv->data_rate);
+       mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n",
+                   priv->data_rate);
 
        if (!priv->is_data_rate_auto) {
                while (*ptr) {
@@ -180,9 +180,10 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
                        }
                        ptr++;
                }
-               dev_err(priv->adapter->dev, "previously set fixed data rate %#x"
-                       " is not compatible with the network\n",
-                       priv->data_rate);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "previously set fixed data rate %#x\t"
+                           "is not compatible with the network\n",
+                           priv->data_rate);
 
                ret = -1;
                goto done;
@@ -214,8 +215,9 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
        if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES,
                                     card_rates, card_rates_size)) {
                *out_rates_size = 0;
-               dev_err(priv->adapter->dev, "%s: cannot get common rates\n",
-                       __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: cannot get common rates\n",
+                           __func__);
                return -1;
        }
 
@@ -246,8 +248,9 @@ mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer)
         * parameter buffer pointer.
         */
        if (priv->wps_ie_len) {
-               dev_dbg(priv->adapter->dev, "cmd: append wps ie %d to %p\n",
-                       priv->wps_ie_len, *buffer);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: append wps ie %d to %p\n",
+                           priv->wps_ie_len, *buffer);
 
                /* Wrap the generic IE buffer with a pass through TLV type */
                ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE);
@@ -292,8 +295,9 @@ mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer)
         *   parameter buffer pointer.
         */
        if (priv->wapi_ie_len) {
-               dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n",
-                       priv->wapi_ie_len, *buffer);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: append wapi ie %d to %p\n",
+                           priv->wapi_ie_len, *buffer);
 
                /* Wrap the generic IE buffer with a pass through TLV type */
                ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE);
@@ -453,8 +457,8 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
        rates_tlv->header.len = cpu_to_le16((u16) rates_size);
        memcpy(rates_tlv->rates, rates, rates_size);
        pos += sizeof(rates_tlv->header) + rates_size;
-       dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n",
-               rates_size);
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n",
+                   rates_size);
 
        /* Add the Authentication type to be used for Auth frames */
        auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
@@ -487,14 +491,14 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
                       sizeof(struct mwifiex_chan_scan_param_set));
                chan_tlv->chan_scan_param[0].chan_number =
                        (bss_desc->phy_param_set.ds_param_set.current_chan);
-               dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n",
-                       chan_tlv->chan_scan_param[0].chan_number);
+               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
 
                chan_tlv->chan_scan_param[0].radio_type =
                        mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
-               dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n",
-                       chan_tlv->chan_scan_param[0].radio_type);
+               mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
                pos += sizeof(chan_tlv->header) +
                        sizeof(struct mwifiex_chan_scan_param_set);
        }
@@ -544,8 +548,9 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
                tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
 
        tmp_cap &= CAPINFO_MASK;
-       dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
-               tmp_cap, CAPINFO_MASK);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
+                   tmp_cap, CAPINFO_MASK);
        assoc->cap_info_bitmap = cpu_to_le16(tmp_cap);
 
        return 0;
@@ -645,9 +650,11 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 
        if (status_code) {
                priv->adapter->dbg.num_cmd_assoc_failure++;
-               dev_err(priv->adapter->dev,
-                       "ASSOC_RESP: failed, status code=%d err=%#x a_id=%#x\n",
-                       status_code, cap_info, le16_to_cpu(assoc_rsp->a_id));
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "ASSOC_RESP: failed,\t"
+                           "status code=%d err=%#x a_id=%#x\n",
+                           status_code, cap_info,
+                           le16_to_cpu(assoc_rsp->a_id));
 
                if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) {
                        if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT)
@@ -671,8 +678,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
        /* Set the attempted BSSID Index to current */
        bss_desc = priv->attempted_bss_desc;
 
-       dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n",
-               bss_desc->ssid.ssid);
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n",
+                   bss_desc->ssid.ssid);
 
        /* Make a copy of current BSSID descriptor */
        memcpy(&priv->curr_bss_params.bss_descriptor,
@@ -702,8 +709,9 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
                        = ((bss_desc->wmm_ie.qos_info_bitmap &
                                IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);
 
-       dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
-               priv->curr_pkt_filter);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
+                   priv->curr_pkt_filter);
        if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
                priv->wpa_is_gtk_set = false;
 
@@ -719,8 +727,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
        }
 
        if (enable_data)
-               dev_dbg(priv->adapter->dev,
-                       "info: post association, re-enabling data flow\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: post association, re-enabling data flow\n");
 
        /* Reset SNR/NF/RSSI values */
        priv->data_rssi_last = 0;
@@ -738,7 +746,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 
        priv->adapter->dbg.num_cmd_assoc_success++;
 
-       dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n");
+       mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n");
 
        /* Add the ra_list here for infra mode as there will be only 1 ra
           always */
@@ -825,8 +833,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 
        memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
 
-       dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
-               adhoc_start->ssid);
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n",
+                   adhoc_start->ssid);
 
        memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
        memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
@@ -858,12 +866,14 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
        }
 
        if (!priv->adhoc_channel) {
-               dev_err(adapter->dev, "ADHOC_S_CMD: adhoc_channel cannot be 0\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "ADHOC_S_CMD: adhoc_channel cannot be 0\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
-               priv->adhoc_channel);
+       mwifiex_dbg(adapter, INFO,
+                   "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
+                   priv->adhoc_channel);
 
        priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel;
        priv->curr_bss_params.band = adapter->adhoc_start_band;
@@ -895,13 +905,14 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
        /* Set up privacy in bss_desc */
        if (priv->sec_info.encryption_mode) {
                /* Ad-Hoc capability privacy on */
-               dev_dbg(adapter->dev,
-                       "info: ADHOC_S_CMD: wep_status set privacy to WEP\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: ADHOC_S_CMD: wep_status set privacy to WEP\n");
                bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
                tmp_cap |= WLAN_CAPABILITY_PRIVACY;
        } else {
-               dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set,"
-                               " setting privacy to ACCEPT ALL\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: ADHOC_S_CMD: wep_status NOT set,\t"
+                           "setting privacy to ACCEPT ALL\n");
                bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
        }
 
@@ -912,8 +923,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
                                     HostCmd_ACT_GEN_SET, 0,
                                     &priv->curr_pkt_filter, false)) {
-                       dev_err(adapter->dev,
-                               "ADHOC_S_CMD: G Protection config failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "ADHOC_S_CMD: G Protection config failed\n");
                        return -1;
                }
        }
@@ -928,10 +939,10 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
        memcpy(&priv->curr_bss_params.data_rates,
               &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates);
 
-       dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%4ph\n",
-               adhoc_start->data_rate);
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n",
+                   adhoc_start->data_rate);
 
-       dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
+       mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
 
        if (IS_SUPPORT_MULTI_BANDS(adapter)) {
                /* Append a channel TLV */
@@ -945,8 +956,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                chan_tlv->chan_scan_param[0].chan_number =
                        (u8) priv->curr_bss_params.bss_descriptor.channel;
 
-               dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n",
-                       chan_tlv->chan_scan_param[0].chan_number);
+               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
 
                chan_tlv->chan_scan_param[0].radio_type
                       = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
@@ -961,8 +972,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                                chan_tlv->chan_scan_param[0].radio_type |=
                                        (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
                }
-               dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n",
-                       chan_tlv->chan_scan_param[0].radio_type);
+               mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
                pos += sizeof(chan_tlv->header) +
                        sizeof(struct mwifiex_chan_scan_param_set);
                cmd_append_size +=
@@ -1084,8 +1095,8 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
                                     HostCmd_ACT_GEN_SET, 0,
                                     &curr_pkt_filter, false)) {
-                       dev_err(priv->adapter->dev,
-                               "ADHOC_J_CMD: G Protection config failed\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "ADHOC_J_CMD: G Protection config failed\n");
                        return -1;
                }
        }
@@ -1116,14 +1127,15 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
 
        tmp_cap &= CAPINFO_MASK;
 
-       dev_dbg(priv->adapter->dev,
-               "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
-               tmp_cap, CAPINFO_MASK);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
+                   tmp_cap, CAPINFO_MASK);
 
        /* Information on BSSID descriptor passed to FW */
-       dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
-               adhoc_join->bss_descriptor.bssid,
-               adhoc_join->bss_descriptor.ssid);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
+                   adhoc_join->bss_descriptor.bssid,
+                   adhoc_join->bss_descriptor.ssid);
 
        for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
                    bss_desc->supported_rates[i]; i++)
@@ -1159,14 +1171,14 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                       sizeof(struct mwifiex_chan_scan_param_set));
                chan_tlv->chan_scan_param[0].chan_number =
                        (bss_desc->phy_param_set.ds_param_set.current_chan);
-               dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan=%d\n",
-                       chan_tlv->chan_scan_param[0].chan_number);
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n",
+                           chan_tlv->chan_scan_param[0].chan_number);
 
                chan_tlv->chan_scan_param[0].radio_type =
                        mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
-               dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band=%d\n",
-                       chan_tlv->chan_scan_param[0].radio_type);
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n",
+                           chan_tlv->chan_scan_param[0].radio_type);
                pos += sizeof(chan_tlv->header) +
                                sizeof(struct mwifiex_chan_scan_param_set);
                cmd_append_size += sizeof(chan_tlv->header) +
@@ -1220,7 +1232,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
        /* Join result code 0 --> SUCCESS */
        reason_code = le16_to_cpu(resp->result);
        if (reason_code) {
-               dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n");
+               mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n");
                if (priv->media_connected)
                        mwifiex_reset_connect_state(priv, reason_code);
 
@@ -1235,8 +1247,8 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
        priv->media_connected = true;
 
        if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
-               dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n",
-                       bss_desc->ssid.ssid);
+               mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n",
+                           bss_desc->ssid.ssid);
 
                /* Update the created network descriptor with the new BSSID */
                memcpy(bss_desc->mac_address,
@@ -1248,8 +1260,9 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
                 * Now the join cmd should be successful.
                 * If BSSID has changed use SSID to compare instead of BSSID
                 */
-               dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n",
-                       bss_desc->ssid.ssid);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ADHOC_J_RESP %s\n",
+                           bss_desc->ssid.ssid);
 
                /*
                 * Make a copy of current BSSID descriptor, only needed for
@@ -1262,10 +1275,10 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
                priv->adhoc_state = ADHOC_JOINED;
        }
 
-       dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n",
-               priv->adhoc_channel);
-       dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n",
-               priv->curr_bss_params.bss_descriptor.mac_address);
+       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n",
+                   priv->adhoc_channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n",
+                   priv->curr_bss_params.bss_descriptor.mac_address);
 
        if (!netif_carrier_ok(priv->netdev))
                netif_carrier_on(priv->netdev);
@@ -1327,12 +1340,12 @@ int
 mwifiex_adhoc_start(struct mwifiex_private *priv,
                    struct cfg80211_ssid *adhoc_ssid)
 {
-       dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",
-               priv->adhoc_channel);
-       dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
-               priv->curr_bss_params.bss_descriptor.channel);
-       dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
-               priv->curr_bss_params.band);
+       mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n",
+                   priv->adhoc_channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n",
+                   priv->curr_bss_params.bss_descriptor.channel);
+       mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n",
+                   priv->curr_bss_params.band);
 
        if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
            priv->adapter->config_bands & BAND_AAC)
@@ -1353,14 +1366,16 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
 int mwifiex_adhoc_join(struct mwifiex_private *priv,
                       struct mwifiex_bssdescriptor *bss_desc)
 {
-       dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n",
-               priv->curr_bss_params.bss_descriptor.ssid.ssid);
-       dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n",
-               priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
-       dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n",
-               bss_desc->ssid.ssid);
-       dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n",
-               bss_desc->ssid.ssid_len);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: adhoc join: curr_bss ssid =%s\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: adhoc join: curr_bss ssid_len =%u\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n",
+                   bss_desc->ssid.ssid);
+       mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n",
+                   bss_desc->ssid.ssid_len);
 
        /* Check if the requested SSID is already joined */
        if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
@@ -1368,8 +1383,9 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
                              &priv->curr_bss_params.bss_descriptor.ssid) &&
            (priv->curr_bss_params.bss_descriptor.bss_mode ==
                                                        NL80211_IFTYPE_ADHOC)) {
-               dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID"
-                       " is the same as current; not attempting to re-join\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ADHOC_J_CMD: new ad-hoc SSID\t"
+                           "is the same as current; not attempting to re-join\n");
                return -1;
        }
 
@@ -1380,10 +1396,12 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
        else
                mwifiex_set_ba_params(priv);
 
-       dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
-               priv->curr_bss_params.bss_descriptor.channel);
-       dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",
-               priv->curr_bss_params.band);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: curr_bss_params.channel = %d\n",
+                   priv->curr_bss_params.bss_descriptor.channel);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: curr_bss_params.band = %c\n",
+                   priv->curr_bss_params.band);
 
        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
                                HostCmd_ACT_GEN_SET, 0, bss_desc, true);
index 213aa986e87aba6786f2130de1b3e037d0d3149d..3ba4e0e04223bcde4fd0da162db6bb6db6160b62 100644 (file)
 
 #define VERSION        "1.0"
 
+static unsigned int debug_mask = MWIFIEX_DEFAULT_DEBUG_MASK;
+module_param(debug_mask, uint, 0);
+MODULE_PARM_DESC(debug_mask, "bitmap for debug flags");
+
 const char driver_version[] = "mwifiex " VERSION " (%s) ";
 static char *cal_data_cfg;
 module_param(cal_data_cfg, charp, 0);
@@ -63,6 +67,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
 
        /* Save interface specific operations in adapter */
        memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
+       adapter->debug_mask = debug_mask;
 
        /* card specific initialization has been deferred until now .. */
        if (adapter->if_ops.init_if)
@@ -89,7 +94,8 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
        return 0;
 
 error:
-       dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
+       mwifiex_dbg(adapter, ERROR,
+                   "info: leave mwifiex_register with error\n");
 
        for (i = 0; i < adapter->priv_num; i++)
                kfree(adapter->priv[i]);
@@ -454,8 +460,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        struct wireless_dev *wdev;
 
        if (!firmware) {
-               dev_err(adapter->dev,
-                       "Failed to get firmware %s\n", adapter->fw_name);
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to get firmware %s\n", adapter->fw_name);
                goto err_dnld_fw;
        }
 
@@ -471,13 +477,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        if (ret == -1)
                goto err_dnld_fw;
 
-       dev_notice(adapter->dev, "WLAN FW is active\n");
+       mwifiex_dbg(adapter, MSG, "WLAN FW is active\n");
 
        if (cal_data_cfg) {
                if ((request_firmware(&adapter->cal_data, cal_data_cfg,
                                      adapter->dev)) < 0)
-                       dev_err(adapter->dev,
-                               "Cal data request_firmware() failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Cal data request_firmware() failed\n");
        }
 
        /* enable host interrupt after fw dnld is successful */
@@ -502,12 +508,14 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 
        priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
        if (mwifiex_register_cfg80211(adapter)) {
-               dev_err(adapter->dev, "cannot register with cfg80211\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot register with cfg80211\n");
                goto err_init_fw;
        }
 
        if (mwifiex_init_channel_scan_gap(adapter)) {
-               dev_err(adapter->dev, "could not init channel stats table\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "could not init channel stats table\n");
                goto err_init_fw;
        }
 
@@ -521,7 +529,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM,
                                        NL80211_IFTYPE_STATION, NULL, NULL);
        if (IS_ERR(wdev)) {
-               dev_err(adapter->dev, "cannot create default STA interface\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot create default STA interface\n");
                rtnl_unlock();
                goto err_add_intf;
        }
@@ -530,7 +539,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
                wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM,
                                                NL80211_IFTYPE_AP, NULL, NULL);
                if (IS_ERR(wdev)) {
-                       dev_err(adapter->dev, "cannot create AP interface\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create AP interface\n");
                        rtnl_unlock();
                        goto err_add_intf;
                }
@@ -541,8 +551,8 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
                                                NL80211_IFTYPE_P2P_CLIENT, NULL,
                                                NULL);
                if (IS_ERR(wdev)) {
-                       dev_err(adapter->dev,
-                               "cannot create p2p client interface\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cannot create p2p client interface\n");
                        rtnl_unlock();
                        goto err_add_intf;
                }
@@ -550,7 +560,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        rtnl_unlock();
 
        mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
-       dev_notice(adapter->dev, "driver_version = %s\n", fmt);
+       mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt);
        goto done;
 
 err_add_intf:
@@ -560,7 +570,8 @@ err_init_fw:
        if (adapter->if_ops.disable_int)
                adapter->if_ops.disable_int(adapter);
 err_dnld_fw:
-       pr_debug("info: %s: unregister device\n", __func__);
+       mwifiex_dbg(adapter, ERROR,
+                   "info: %s: unregister device\n", __func__);
        if (adapter->if_ops.unregister_dev)
                adapter->if_ops.unregister_dev(adapter);
 
@@ -601,8 +612,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
                                      adapter->dev, GFP_KERNEL, adapter,
                                      mwifiex_fw_dpc);
        if (ret < 0)
-               dev_err(adapter->dev,
-                       "request_firmware_nowait() returned error %d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "request_firmware_nowait error %d\n", ret);
        return ret;
 }
 
@@ -628,7 +639,8 @@ mwifiex_close(struct net_device *dev)
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
        if (priv->scan_request) {
-               dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "aborting scan on ndo_stop\n");
                cfg80211_scan_done(priv->scan_request, 1);
                priv->scan_request = NULL;
                priv->scan_aborting = true;
@@ -649,7 +661,8 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
                txq = netdev_get_tx_queue(priv->netdev, index);
                if (!netif_tx_queue_stopped(txq)) {
                        netif_tx_stop_queue(txq);
-                       dev_dbg(priv->adapter->dev, "stop queue: %d\n", index);
+                       mwifiex_dbg(priv->adapter, DATA,
+                                   "stop queue: %d\n", index);
                }
        }
 
@@ -714,8 +727,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct mwifiex_txinfo *tx_info;
        bool multicast;
 
-       dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
-               jiffies, priv->bss_type, priv->bss_num);
+       mwifiex_dbg(priv->adapter, DATA,
+                   "data: %lu BSS(%d-%d): Data <= kernel\n",
+                   jiffies, priv->bss_type, priv->bss_num);
 
        if (priv->adapter->surprise_removed) {
                kfree_skb(skb);
@@ -723,28 +737,31 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
        if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
-               dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Tx: bad skb len %d\n", skb->len);
                kfree_skb(skb);
                priv->stats.tx_dropped++;
                return 0;
        }
        if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
-               dev_dbg(priv->adapter->dev,
-                       "data: Tx: insufficient skb headroom %d\n",
-                       skb_headroom(skb));
+               mwifiex_dbg(priv->adapter, DATA,
+                           "data: Tx: insufficient skb headroom %d\n",
+                           skb_headroom(skb));
                /* Insufficient skb headroom - allocate a new skb */
                new_skb =
                        skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
                if (unlikely(!new_skb)) {
-                       dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Tx: cannot alloca new_skb\n");
                        kfree_skb(skb);
                        priv->stats.tx_dropped++;
                        return 0;
                }
                kfree_skb(skb);
                skb = new_skb;
-               dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n",
-                       skb_headroom(skb));
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: new skb headroomd %d\n",
+                           skb_headroom(skb));
        }
 
        tx_info = MWIFIEX_SKB_TXCB(skb);
@@ -802,8 +819,8 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr)
        if (!ret)
                memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
        else
-               dev_err(priv->adapter->dev,
-                       "set mac address failed: ret=%d\n", ret);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "set mac address failed: ret=%d\n", ret);
 
        memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
 
@@ -841,20 +858,22 @@ mwifiex_tx_timeout(struct net_device *dev)
 
        priv->num_tx_timeout++;
        priv->tx_timeout_cnt++;
-       dev_err(priv->adapter->dev,
-               "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
-               jiffies, priv->tx_timeout_cnt, priv->bss_type, priv->bss_num);
+       mwifiex_dbg(priv->adapter, ERROR,
+                   "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
+                   jiffies, priv->tx_timeout_cnt, priv->bss_type,
+                   priv->bss_num);
        mwifiex_set_trans_start(dev);
 
        if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD &&
            priv->adapter->if_ops.card_reset) {
-               dev_err(priv->adapter->dev,
-                       "tx_timeout_cnt exceeds threshold. Triggering card reset!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tx_timeout_cnt exceeds threshold.\t"
+                           "Triggering card reset!\n");
                priv->adapter->if_ops.card_reset(priv->adapter);
        }
 }
 
-void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
 {
        void *p;
        char drv_version[64];
@@ -867,10 +886,11 @@ void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
 
        if (adapter->drv_info_dump) {
                vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
                adapter->drv_info_size = 0;
        }
 
-       dev_info(adapter->dev, "=== DRIVER INFO DUMP START===\n");
+       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
 
        adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
 
@@ -938,12 +958,12 @@ void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
        }
 
        if (adapter->iface_type == MWIFIEX_SDIO) {
-               p += sprintf(p, "\n=== SDIO register DUMP===\n");
+               p += sprintf(p, "\n=== SDIO register dump===\n");
                if (adapter->if_ops.reg_dump)
                        p += adapter->if_ops.reg_dump(adapter, p);
        }
 
-       p += sprintf(p, "\n=== MORE DEBUG INFORMATION\n");
+       p += sprintf(p, "\n=== more debug information\n");
        debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL);
        if (debug_info) {
                for (i = 0; i < adapter->priv_num; i++) {
@@ -958,9 +978,99 @@ void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
        }
 
        adapter->drv_info_size = p - adapter->drv_info_dump;
-       dev_info(adapter->dev, "=== DRIVER INFO DUMP END===\n");
+       mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
+}
+EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
+
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
+{
+       u8 idx, *dump_data, *fw_dump_ptr;
+       u32 dump_len;
+
+       dump_len = (strlen("========Start dump driverinfo========\n") +
+                      adapter->drv_info_size +
+                      strlen("\n========End dump========\n"));
+
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                               &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       dump_len += (strlen("========Start dump ") +
+                                       strlen(entry->mem_name) +
+                                       strlen("========\n") +
+                                       (entry->mem_size + 1) +
+                                       strlen("\n========End dump========\n"));
+               }
+       }
+
+       dump_data = vzalloc(dump_len + 1);
+       if (!dump_data)
+               goto done;
+
+       fw_dump_ptr = dump_data;
+
+       /* Dump all the memory data into single file, a userspace script will
+        * be used to split all the memory data to multiple files
+        */
+       mwifiex_dbg(adapter, MSG,
+                   "== mwifiex dump information to /sys/class/devcoredump start");
+
+       strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
+       fw_dump_ptr += strlen("========Start dump driverinfo========\n");
+       memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size);
+       fw_dump_ptr += adapter->drv_info_size;
+       strcpy(fw_dump_ptr, "\n========End dump========\n");
+       fw_dump_ptr += strlen("\n========End dump========\n");
+
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                                       &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       strcpy(fw_dump_ptr, "========Start dump ");
+                       fw_dump_ptr += strlen("========Start dump ");
+
+                       strcpy(fw_dump_ptr, entry->mem_name);
+                       fw_dump_ptr += strlen(entry->mem_name);
+
+                       strcpy(fw_dump_ptr, "========\n");
+                       fw_dump_ptr += strlen("========\n");
+
+                       memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
+                       fw_dump_ptr += entry->mem_size;
+
+                       strcpy(fw_dump_ptr, "\n========End dump========\n");
+                       fw_dump_ptr += strlen("\n========End dump========\n");
+               }
+       }
+
+       /* device dump data will be free in device coredump release function
+        * after 5 min
+        */
+       dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
+       mwifiex_dbg(adapter, MSG,
+                   "== mwifiex dump information to /sys/class/devcoredump end");
+
+done:
+       for (idx = 0; idx < adapter->num_mem_types; idx++) {
+               struct memory_type_mapping *entry =
+                       &adapter->mem_type_mapping_tbl[idx];
+
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
+
+       if (adapter->drv_info_dump) {
+               vfree(adapter->drv_info_dump);
+               adapter->drv_info_dump = NULL;
+               adapter->drv_info_size = 0;
+       }
 }
-EXPORT_SYMBOL_GPL(mwifiex_dump_drv_info);
+EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
 
 /*
  * CFG802.11 network device handler for statistics retrieval.
@@ -1229,21 +1339,24 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
                }
        }
 
-       dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: calling mwifiex_shutdown_drv...\n");
        adapter->init_wait_q_woken = false;
 
        if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
                wait_event_interruptible(adapter->init_wait_q,
                                         adapter->init_wait_q_woken);
-       dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: mwifiex_shutdown_drv done\n");
        if (atomic_read(&adapter->rx_pending) ||
            atomic_read(&adapter->tx_pending) ||
            atomic_read(&adapter->cmd_pending)) {
-               dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
-                      "cmd_pending=%d\n",
-                      atomic_read(&adapter->rx_pending),
-                      atomic_read(&adapter->tx_pending),
-                      atomic_read(&adapter->cmd_pending));
+               mwifiex_dbg(adapter, ERROR,
+                           "rx_pending=%d, tx_pending=%d,\t"
+                           "cmd_pending=%d\n",
+                           atomic_read(&adapter->rx_pending),
+                           atomic_read(&adapter->tx_pending),
+                           atomic_read(&adapter->cmd_pending));
        }
 
        for (i = 0; i < adapter->priv_num; i++) {
@@ -1263,11 +1376,13 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
        wiphy_free(adapter->wiphy);
 
        /* Unregister device */
-       dev_dbg(adapter->dev, "info: unregister device\n");
+       mwifiex_dbg(adapter, INFO,
+                   "info: unregister device\n");
        if (adapter->if_ops.unregister_dev)
                adapter->if_ops.unregister_dev(adapter);
        /* Free adapter structure */
-       dev_dbg(adapter->dev, "info: free adapter\n");
+       mwifiex_dbg(adapter, INFO,
+                   "info: free adapter\n");
        mwifiex_free_adapter(adapter);
 
 exit_remove:
index fe1256044a6c9bca9b9e8475cf8a0487ca7cd0b8..5a6c1c76b33bc173c0ab55465ec1ad2885675dde 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/of.h>
 #include <linux/idr.h>
 #include <linux/inetdevice.h>
+#include <linux/devcoredump.h>
 
 #include "decl.h"
 #include "ioctl.h"
@@ -147,6 +148,54 @@ enum {
 /* Address alignment */
 #define MWIFIEX_ALIGN_ADDR(p, a) (((long)(p) + (a) - 1) & ~((a) - 1))
 
+/**
+ *enum mwifiex_debug_level  -  marvell wifi debug level
+ */
+enum MWIFIEX_DEBUG_LEVEL {
+       MWIFIEX_DBG_MSG         = 0x00000001,
+       MWIFIEX_DBG_FATAL       = 0x00000002,
+       MWIFIEX_DBG_ERROR       = 0x00000004,
+       MWIFIEX_DBG_DATA        = 0x00000008,
+       MWIFIEX_DBG_CMD         = 0x00000010,
+       MWIFIEX_DBG_EVENT       = 0x00000020,
+       MWIFIEX_DBG_INTR        = 0x00000040,
+       MWIFIEX_DBG_IOCTL       = 0x00000080,
+
+       MWIFIEX_DBG_MPA_D       = 0x00008000,
+       MWIFIEX_DBG_DAT_D       = 0x00010000,
+       MWIFIEX_DBG_CMD_D       = 0x00020000,
+       MWIFIEX_DBG_EVT_D       = 0x00040000,
+       MWIFIEX_DBG_FW_D        = 0x00080000,
+       MWIFIEX_DBG_IF_D        = 0x00100000,
+
+       MWIFIEX_DBG_ENTRY       = 0x10000000,
+       MWIFIEX_DBG_WARN        = 0x20000000,
+       MWIFIEX_DBG_INFO        = 0x40000000,
+       MWIFIEX_DBG_DUMP        = 0x80000000,
+
+       MWIFIEX_DBG_ANY         = 0xffffffff
+};
+
+#define MWIFIEX_DEFAULT_DEBUG_MASK     (MWIFIEX_DBG_MSG | \
+                                       MWIFIEX_DBG_FATAL | \
+                                       MWIFIEX_DBG_ERROR)
+
+#define mwifiex_dbg(adapter, dbg_mask, fmt, args...)           \
+do {                                                           \
+       if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask)     \
+               if ((adapter)->dev)                             \
+                       dev_info((adapter)->dev, fmt, ## args); \
+} while (0)
+
+#define DEBUG_DUMP_DATA_MAX_LEN                128
+#define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len)     \
+do {                                                           \
+       if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask)     \
+               print_hex_dump(KERN_DEBUG, str,                 \
+                              DUMP_PREFIX_OFFSET, 16, 1,       \
+                              buf, len, false);                \
+} while (0)
+
 struct mwifiex_dbg {
        u32 num_cmd_host_to_card_failure;
        u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -451,7 +500,7 @@ enum rdwr_status {
 };
 
 enum mwifiex_iface_work_flags {
-       MWIFIEX_IFACE_WORK_FW_DUMP,
+       MWIFIEX_IFACE_WORK_DEVICE_DUMP,
        MWIFIEX_IFACE_WORK_CARD_RESET,
 };
 
@@ -611,6 +660,7 @@ struct mwifiex_private {
        struct delayed_work dfs_chan_sw_work;
        struct cfg80211_beacon_data beacon_after;
        struct mwifiex_11h_intf_state state_11h;
+       struct mwifiex_ds_mem_rw mem_rw;
 };
 
 
@@ -740,8 +790,8 @@ struct mwifiex_if_ops {
        int (*init_fw_port) (struct mwifiex_adapter *);
        int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
        void (*card_reset) (struct mwifiex_adapter *);
-       void (*fw_dump)(struct mwifiex_adapter *);
        int (*reg_dump)(struct mwifiex_adapter *, char *);
+       void (*device_dump)(struct mwifiex_adapter *);
        int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
        void (*iface_work)(struct work_struct *work);
        void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
@@ -750,6 +800,7 @@ struct mwifiex_if_ops {
 
 struct mwifiex_adapter {
        u8 iface_type;
+       unsigned int debug_mask;
        struct mwifiex_iface_comb iface_limit;
        struct mwifiex_iface_comb curr_iface_comb;
        struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
@@ -900,7 +951,6 @@ struct mwifiex_adapter {
        u8 key_api_major_ver, key_api_minor_ver;
        struct memory_type_mapping *mem_type_mapping_tbl;
        u8 num_mem_types;
-       u8 curr_mem_idx;
        void *drv_info_dump;
        u32 drv_info_size;
        bool scan_chan_gap_enabled;
@@ -1434,7 +1484,8 @@ void mwifiex_hist_data_add(struct mwifiex_private *priv,
 u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
                            u8 rx_rate, u8 ht_info);
 
-void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter);
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
+void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
 void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
 void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
 
index bcc7751d883c3773b558ef8c8b8bb8c3a8a3c474..77b9055a2d147411515b5875f67b90210938ac9b 100644 (file)
@@ -57,7 +57,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 
        mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
        if (pci_dma_mapping_error(card->dev, mapping.addr)) {
-               dev_err(adapter->dev, "failed to map pci memory!\n");
+               mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
                return -1;
        }
        mapping.len = size;
@@ -89,8 +89,9 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
 
        if (card->sleep_cookie_vbase) {
                cookie_addr = (u32 *)card->sleep_cookie_vbase;
-               dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n",
-                       *cookie_addr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: ACCESS_HW: sleep cookie=0x%x\n",
+                           *cookie_addr);
                if (*cookie_addr == FW_AWAKE_COOKIE)
                        return true;
        }
@@ -164,7 +165,8 @@ static int mwifiex_pcie_resume(struct device *dev)
        adapter = card->adapter;
 
        if (!adapter->is_suspended) {
-               dev_warn(adapter->dev, "Device already resumed\n");
+               mwifiex_dbg(adapter, WARN,
+                           "Device already resumed\n");
                return 0;
        }
 
@@ -361,16 +363,16 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
                sleep_cookie = *(u32 *)buffer;
 
                if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
-                       dev_dbg(adapter->dev,
-                               "sleep cookie found at count %d\n", count);
+                       mwifiex_dbg(adapter, INFO,
+                                   "sleep cookie found at count %d\n", count);
                        break;
                }
                usleep_range(20, 30);
        }
 
        if (count >= max_delay_loop_cnt)
-               dev_dbg(adapter->dev,
-                       "max count reached while accessing sleep cookie\n");
+               mwifiex_dbg(adapter, INFO,
+                           "max count reached while accessing sleep cookie\n");
 }
 
 /* This function wakes up the card by reading fw_status register. */
@@ -380,20 +382,23 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
        struct pcie_service_card *card = adapter->card;
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
-       dev_dbg(adapter->dev, "event: Wakeup device...\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "event: Wakeup device...\n");
 
        if (reg->sleep_cookie)
                mwifiex_pcie_dev_wakeup_delay(adapter);
 
        /* Reading fw_status register will wakeup device */
        if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
-               dev_warn(adapter->dev, "Reading fw_status register failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Reading fw_status register failed\n");
                return -1;
        }
 
        if (reg->sleep_cookie) {
                mwifiex_pcie_dev_wakeup_delay(adapter);
-               dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
+               mwifiex_dbg(adapter, INFO,
+                           "PCIE wakeup: Setting PS_STATE_AWAKE\n");
                adapter->ps_state = PS_STATE_AWAKE;
        }
 
@@ -407,7 +412,8 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "cmd: Wakeup device completed\n");
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: Wakeup device completed\n");
 
        return 0;
 }
@@ -423,7 +429,8 @@ static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
        if (mwifiex_pcie_ok_to_access_hw(adapter)) {
                if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
                                      0x00000000)) {
-                       dev_warn(adapter->dev, "Disable host interrupt failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Disable host interrupt failed\n");
                        return -1;
                }
        }
@@ -443,7 +450,8 @@ static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
                /* Simply write the mask to the register */
                if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
                                      HOST_INTR_MASK)) {
-                       dev_warn(adapter->dev, "Enable host interrupt failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Enable host interrupt failed\n");
                        return -1;
                }
        }
@@ -499,8 +507,8 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
                skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
                                                  GFP_KERNEL | GFP_DMA);
                if (!skb) {
-                       dev_err(adapter->dev,
-                               "Unable to allocate skb for RX ring.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb for RX ring.\n");
                        kfree(card->rxbd_ring_vbase);
                        return -ENOMEM;
                }
@@ -512,10 +520,10 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
 
                buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
-               dev_dbg(adapter->dev,
-                       "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
-                       skb, skb->len, skb->data, (u32)buf_pa,
-                       (u32)((u64)buf_pa >> 32));
+               mwifiex_dbg(adapter, INFO,
+                           "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+                           skb, skb->len, skb->data, (u32)buf_pa,
+                           (u32)((u64)buf_pa >> 32));
 
                card->rx_buf_list[i] = skb;
                if (reg->pfu_enabled) {
@@ -556,8 +564,8 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
                /* Allocate skb here so that firmware can DMA data from it */
                skb = dev_alloc_skb(MAX_EVENT_SIZE);
                if (!skb) {
-                       dev_err(adapter->dev,
-                               "Unable to allocate skb for EVENT buf.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb for EVENT buf.\n");
                        kfree(card->evtbd_ring_vbase);
                        return -ENOMEM;
                }
@@ -569,10 +577,10 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
 
                buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
-               dev_dbg(adapter->dev,
-                       "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
-                       skb, skb->len, skb->data, (u32)buf_pa,
-                       (u32)((u64)buf_pa >> 32));
+               mwifiex_dbg(adapter, EVENT,
+                           "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+                           skb, skb->len, skb->data, (u32)buf_pa,
+                           (u32)((u64)buf_pa >> 32));
 
                card->evt_buf_list[i] = skb;
                card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
@@ -715,21 +723,23 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
                card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
                                       MWIFIEX_MAX_TXRX_BD;
 
-       dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n",
-               card->txbd_ring_size);
+       mwifiex_dbg(adapter, INFO,
+                   "info: txbd_ring: Allocating %d bytes\n",
+                   card->txbd_ring_size);
        card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
                                                     card->txbd_ring_size,
                                                     &card->txbd_ring_pbase);
        if (!card->txbd_ring_vbase) {
-               dev_err(adapter->dev,
-                       "allocate consistent memory (%d bytes) failed!\n",
-                       card->txbd_ring_size);
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->txbd_ring_size);
                return -ENOMEM;
        }
-       dev_dbg(adapter->dev,
-               "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
-               card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
-               (u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size);
+       mwifiex_dbg(adapter, DATA,
+                   "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
+                   card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
+                   (u32)((u64)card->txbd_ring_pbase >> 32),
+                   card->txbd_ring_size);
 
        return mwifiex_init_txq_ring(adapter);
 }
@@ -777,23 +787,24 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
                card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
                                       MWIFIEX_MAX_TXRX_BD;
 
-       dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n",
-               card->rxbd_ring_size);
+       mwifiex_dbg(adapter, INFO,
+                   "info: rxbd_ring: Allocating %d bytes\n",
+                   card->rxbd_ring_size);
        card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
                                                     card->rxbd_ring_size,
                                                     &card->rxbd_ring_pbase);
        if (!card->rxbd_ring_vbase) {
-               dev_err(adapter->dev,
-                       "allocate consistent memory (%d bytes) failed!\n",
-                       card->rxbd_ring_size);
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->rxbd_ring_size);
                return -ENOMEM;
        }
 
-       dev_dbg(adapter->dev,
-               "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
-               card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
-               (u32)((u64)card->rxbd_ring_pbase >> 32),
-               card->rxbd_ring_size);
+       mwifiex_dbg(adapter, DATA,
+                   "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
+                   card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
+                   (u32)((u64)card->rxbd_ring_pbase >> 32),
+                   card->rxbd_ring_size);
 
        return mwifiex_init_rxq_ring(adapter);
 }
@@ -840,23 +851,24 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
        card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
                                MWIFIEX_MAX_EVT_BD;
 
-       dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n",
+       mwifiex_dbg(adapter, INFO,
+                   "info: evtbd_ring: Allocating %d bytes\n",
                card->evtbd_ring_size);
        card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
                                                      card->evtbd_ring_size,
                                                      &card->evtbd_ring_pbase);
        if (!card->evtbd_ring_vbase) {
-               dev_err(adapter->dev,
-                       "allocate consistent memory (%d bytes) failed!\n",
-                       card->evtbd_ring_size);
+               mwifiex_dbg(adapter, ERROR,
+                           "allocate consistent memory (%d bytes) failed!\n",
+                           card->evtbd_ring_size);
                return -ENOMEM;
        }
 
-       dev_dbg(adapter->dev,
-               "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
-               card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
-               (u32)((u64)card->evtbd_ring_pbase >> 32),
-               card->evtbd_ring_size);
+       mwifiex_dbg(adapter, EVENT,
+                   "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
+                   card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
+                   (u32)((u64)card->evtbd_ring_pbase >> 32),
+                   card->evtbd_ring_size);
 
        return mwifiex_pcie_init_evt_ring(adapter);
 }
@@ -895,8 +907,8 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
        /* Allocate memory for receiving command response data */
        skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
        if (!skb) {
-               dev_err(adapter->dev,
-                       "Unable to allocate skb for command response data.\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Unable to allocate skb for command response data.\n");
                return -ENOMEM;
        }
        skb_put(skb, MWIFIEX_UPLD_SIZE);
@@ -944,14 +956,16 @@ static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
        card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
                                                     &card->sleep_cookie_pbase);
        if (!card->sleep_cookie_vbase) {
-               dev_err(adapter->dev, "pci_alloc_consistent failed!\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "pci_alloc_consistent failed!\n");
                return -ENOMEM;
        }
        /* Init val of Sleep Cookie */
        *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
 
-       dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n",
-               *((u32 *)card->sleep_cookie_vbase));
+       mwifiex_dbg(adapter, INFO,
+                   "alloc_scook: sleep cookie=0x%x\n",
+                   *((u32 *)card->sleep_cookie_vbase));
 
        return 0;
 }
@@ -993,8 +1007,8 @@ static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
                 */
                if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                                      CPU_INTR_DNLD_RDY)) {
-                       dev_err(adapter->dev,
-                               "failed to assert dnld-rdy interrupt.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "failed to assert dnld-rdy interrupt.\n");
                        return -1;
                }
        }
@@ -1018,13 +1032,14 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
 
        /* Read the TX ring read pointer set by firmware */
        if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
-               dev_err(adapter->dev,
-                       "SEND COMP: failed to read reg->tx_rdptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "SEND COMP: failed to read reg->tx_rdptr\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
-               card->txbd_rdptr, rdptr);
+       mwifiex_dbg(adapter, DATA,
+                   "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
+                   card->txbd_rdptr, rdptr);
 
        num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
        /* free from previous txbd_rdptr to current txbd_rdptr */
@@ -1038,9 +1053,9 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
                skb = card->tx_buf_list[wrdoneidx];
 
                if (skb) {
-                       dev_dbg(adapter->dev,
-                               "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
-                               skb, wrdoneidx);
+                       mwifiex_dbg(adapter, DATA,
+                                   "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
+                                   skb, wrdoneidx);
                        mwifiex_unmap_pci_memory(adapter, skb,
                                                 PCI_DMA_TODEVICE);
 
@@ -1112,8 +1127,9 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
        __le16 *tmp;
 
        if (!(skb->data && skb->len)) {
-               dev_err(adapter->dev, "%s(): invalid parameter <%p, %#x>\n",
-                       __func__, skb->data, skb->len);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s(): invalid parameter <%p, %#x>\n",
+                           __func__, skb->data, skb->len);
                return -1;
        }
 
@@ -1121,7 +1137,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
                mwifiex_pm_wakeup_card(adapter);
 
        num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
-       dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
+       mwifiex_dbg(adapter, DATA,
+                   "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
                card->txbd_rdptr, card->txbd_wrptr);
        if (mwifiex_pcie_txbd_not_full(card)) {
                u8 *payload;
@@ -1175,39 +1192,40 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
                /* Write the TX ring write pointer in to reg->tx_wrptr */
                if (mwifiex_write_reg(adapter, reg->tx_wrptr,
                                      card->txbd_wrptr | rx_val)) {
-                       dev_err(adapter->dev,
-                               "SEND DATA: failed to write reg->tx_wrptr\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SEND DATA: failed to write reg->tx_wrptr\n");
                        ret = -1;
                        goto done_unmap;
                }
                if ((mwifiex_pcie_txbd_not_full(card)) &&
                    tx_param->next_pkt_len) {
                        /* have more packets and TxBD still can hold more */
-                       dev_dbg(adapter->dev,
-                               "SEND DATA: delay dnld-rdy interrupt.\n");
+                       mwifiex_dbg(adapter, DATA,
+                                   "SEND DATA: delay dnld-rdy interrupt.\n");
                        adapter->data_sent = false;
                } else {
                        /* Send the TX ready interrupt */
                        if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                                              CPU_INTR_DNLD_RDY)) {
-                               dev_err(adapter->dev,
-                                       "SEND DATA: failed to assert dnld-rdy interrupt.\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SEND DATA: failed to assert dnld-rdy interrupt.\n");
                                ret = -1;
                                goto done_unmap;
                        }
                }
-               dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: "
-                       "%#x> and sent packet to firmware successfully\n",
-                       card->txbd_rdptr, card->txbd_wrptr);
+               mwifiex_dbg(adapter, DATA,
+                           "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
+                           "%#x> and sent packet to firmware successfully\n",
+                           card->txbd_rdptr, card->txbd_wrptr);
        } else {
-               dev_dbg(adapter->dev,
-                       "info: TX Ring full, can't send packets to fw\n");
+               mwifiex_dbg(adapter, DATA,
+                           "info: TX Ring full, can't send packets to fw\n");
                adapter->data_sent = true;
                /* Send the TX ready interrupt */
                if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                                      CPU_INTR_DNLD_RDY))
-                       dev_err(adapter->dev,
-                               "SEND DATA: failed to assert door-bell intr\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SEND DATA: failed to assert door-bell intr\n");
                return -EBUSY;
        }
 
@@ -1243,8 +1261,8 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 
        /* Read the RX ring Write pointer set by firmware */
        if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
-               dev_err(adapter->dev,
-                       "RECV DATA: failed to read reg->rx_wrptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "RECV DATA: failed to read reg->rx_wrptr\n");
                ret = -1;
                goto done;
        }
@@ -1277,15 +1295,15 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                rx_len = le16_to_cpu(pkt_len);
                if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
                            rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
-                       dev_err(adapter->dev,
-                               "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
-                               rx_len, card->rxbd_rdptr, wrptr);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
+                                   rx_len, card->rxbd_rdptr, wrptr);
                        dev_kfree_skb_any(skb_data);
                } else {
                        skb_put(skb_data, rx_len);
-                       dev_dbg(adapter->dev,
-                               "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
-                               card->rxbd_rdptr, wrptr, rx_len);
+                       mwifiex_dbg(adapter, DATA,
+                                   "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
+                                   card->rxbd_rdptr, wrptr, rx_len);
                        skb_pull(skb_data, INTF_HEADER_LEN);
                        if (adapter->rx_work_enabled) {
                                skb_queue_tail(&adapter->rx_data_q, skb_data);
@@ -1299,8 +1317,8 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
                                                      GFP_KERNEL | GFP_DMA);
                if (!skb_tmp) {
-                       dev_err(adapter->dev,
-                               "Unable to allocate skb.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Unable to allocate skb.\n");
                        return -ENOMEM;
                }
 
@@ -1311,9 +1329,9 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
 
                buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
 
-               dev_dbg(adapter->dev,
-                       "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
-                       skb_tmp, rd_index);
+               mwifiex_dbg(adapter, INFO,
+                           "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
+                           skb_tmp, rd_index);
                card->rx_buf_list[rd_index] = skb_tmp;
 
                if (reg->pfu_enabled) {
@@ -1336,28 +1354,29 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                                             reg->rx_rollover_ind) ^
                                             reg->rx_rollover_ind);
                }
-               dev_dbg(adapter->dev, "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
-                       card->rxbd_rdptr, wrptr);
+               mwifiex_dbg(adapter, DATA,
+                           "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
+                           card->rxbd_rdptr, wrptr);
 
                tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
                /* Write the RX ring read pointer in to reg->rx_rdptr */
                if (mwifiex_write_reg(adapter, reg->rx_rdptr,
                                      card->rxbd_rdptr | tx_val)) {
-                       dev_err(adapter->dev,
-                               "RECV DATA: failed to write reg->rx_rdptr\n");
+                       mwifiex_dbg(adapter, DATA,
+                                   "RECV DATA: failed to write reg->rx_rdptr\n");
                        ret = -1;
                        goto done;
                }
 
                /* Read the RX ring Write pointer set by firmware */
                if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
-                       dev_err(adapter->dev,
-                               "RECV DATA: failed to read reg->rx_wrptr\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "RECV DATA: failed to read reg->rx_wrptr\n");
                        ret = -1;
                        goto done;
                }
-               dev_dbg(adapter->dev,
-                       "info: RECV DATA: Rcvd packet from fw successfully\n");
+               mwifiex_dbg(adapter, DATA,
+                           "info: RECV DATA: Rcvd packet from fw successfully\n");
                card->rxbd_wrptr = wrptr;
        }
 
@@ -1376,9 +1395,9 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
        if (!(skb->data && skb->len)) {
-               dev_err(adapter->dev,
-                       "Invalid parameter in %s <%p. len %d>\n",
-                       __func__, skb->data, skb->len);
+               mwifiex_dbg(adapter, ERROR,
+                           "Invalid parameter in %s <%p. len %d>\n",
+                           __func__, skb->data, skb->len);
                return -1;
        }
 
@@ -1391,9 +1410,9 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
         * address scratch register
         */
        if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
-               dev_err(adapter->dev,
-                       "%s: failed to write download command to boot code.\n",
-                       __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write download command to boot code.\n",
+                           __func__);
                mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
                return -1;
        }
@@ -1403,18 +1422,18 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
         */
        if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
                              (u32)((u64)buf_pa >> 32))) {
-               dev_err(adapter->dev,
-                       "%s: failed to write download command to boot code.\n",
-                       __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write download command to boot code.\n",
+                           __func__);
                mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
                return -1;
        }
 
        /* Write the command length to cmd_size scratch register */
        if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
-               dev_err(adapter->dev,
-                       "%s: failed to write command len to cmd_size scratch reg\n",
-                       __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to write command len to cmd_size scratch reg\n",
+                           __func__);
                mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
                return -1;
        }
@@ -1422,8 +1441,8 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        /* Ring the door bell */
        if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                              CPU_INTR_DOOR_BELL)) {
-               dev_err(adapter->dev,
-                       "%s: failed to assert door-bell intr\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: failed to assert door-bell intr\n", __func__);
                mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
                return -1;
        }
@@ -1443,8 +1462,8 @@ static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
        /* Write the RX ring read pointer in to reg->rx_rdptr */
        if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
                              tx_wrap)) {
-               dev_err(adapter->dev,
-                       "RECV DATA: failed to write reg->rx_rdptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "RECV DATA: failed to write reg->rx_rdptr\n");
                return -1;
        }
        return 0;
@@ -1462,15 +1481,16 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        u8 *payload = (u8 *)skb->data;
 
        if (!(skb->data && skb->len)) {
-               dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n",
-                       __func__, skb->data, skb->len);
+               mwifiex_dbg(adapter, ERROR,
+                           "Invalid parameter in %s <%p, %#x>\n",
+                           __func__, skb->data, skb->len);
                return -1;
        }
 
        /* Make sure a command response buffer is available */
        if (!card->cmdrsp_buf) {
-               dev_err(adapter->dev,
-                       "No response buffer available, send command failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "No response buffer available, send command failed\n");
                return -EBUSY;
        }
 
@@ -1503,8 +1523,8 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
                   address */
                if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
                                      (u32)cmdrsp_buf_pa)) {
-                       dev_err(adapter->dev,
-                               "Failed to write download cmd to boot code.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write download cmd to boot code.\n");
                        ret = -1;
                        goto done;
                }
@@ -1512,8 +1532,8 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
                   address */
                if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
                                      (u32)((u64)cmdrsp_buf_pa >> 32))) {
-                       dev_err(adapter->dev,
-                               "Failed to write download cmd to boot code.\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write download cmd to boot code.\n");
                        ret = -1;
                        goto done;
                }
@@ -1523,16 +1543,16 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
        if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
                              (u32)cmd_buf_pa)) {
-               dev_err(adapter->dev,
-                       "Failed to write download cmd to boot code.\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write download cmd to boot code.\n");
                ret = -1;
                goto done;
        }
        /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
        if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
                              (u32)((u64)cmd_buf_pa >> 32))) {
-               dev_err(adapter->dev,
-                       "Failed to write download cmd to boot code.\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write download cmd to boot code.\n");
                ret = -1;
                goto done;
        }
@@ -1540,8 +1560,8 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        /* Write the command length to reg->cmd_size */
        if (mwifiex_write_reg(adapter, reg->cmd_size,
                              card->cmd_buf->len)) {
-               dev_err(adapter->dev,
-                       "Failed to write cmd len to reg->cmd_size\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write cmd len to reg->cmd_size\n");
                ret = -1;
                goto done;
        }
@@ -1549,8 +1569,8 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
        /* Ring the door bell */
        if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                              CPU_INTR_DOOR_BELL)) {
-               dev_err(adapter->dev,
-                       "Failed to assert door-bell intr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to assert door-bell intr\n");
                ret = -1;
                goto done;
        }
@@ -1574,7 +1594,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
        u16 rx_len;
        __le16 pkt_len;
 
-       dev_dbg(adapter->dev, "info: Rx CMD Response\n");
+       mwifiex_dbg(adapter, CMD,
+                   "info: Rx CMD Response\n");
 
        mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
 
@@ -1598,8 +1619,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                        if (mwifiex_write_reg(adapter,
                                              PCIE_CPU_INT_EVENT,
                                              CPU_INTR_SLEEP_CFM_DONE)) {
-                               dev_warn(adapter->dev,
-                                        "Write register failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "Write register failed\n");
                                return -1;
                        }
                        mwifiex_delay_for_sleep_cookie(adapter,
@@ -1608,8 +1629,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                               mwifiex_pcie_ok_to_access_hw(adapter))
                                usleep_range(50, 60);
                } else {
-                       dev_err(adapter->dev,
-                               "There is no command but got cmdrsp\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "There is no command but got cmdrsp\n");
                }
                memcpy(adapter->upld_buf, skb->data,
                       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
@@ -1628,15 +1649,15 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                   will prevent firmware from writing to the same response
                   buffer again. */
                if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
-                       dev_err(adapter->dev,
-                               "cmd_done: failed to clear cmd_rsp_addr_lo\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cmd_done: failed to clear cmd_rsp_addr_lo\n");
                        return -1;
                }
                /* Write the upper 32bits of the cmdrsp buffer physical
                   address */
                if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
-                       dev_err(adapter->dev,
-                               "cmd_done: failed to clear cmd_rsp_addr_hi\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "cmd_done: failed to clear cmd_rsp_addr_hi\n");
                        return -1;
                }
        }
@@ -1678,25 +1699,28 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
                mwifiex_pm_wakeup_card(adapter);
 
        if (adapter->event_received) {
-               dev_dbg(adapter->dev, "info: Event being processed, "
-                       "do not process this interrupt just yet\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "info: Event being processed,\t"
+                           "do not process this interrupt just yet\n");
                return 0;
        }
 
        if (rdptr >= MWIFIEX_MAX_EVT_BD) {
-               dev_dbg(adapter->dev, "info: Invalid read pointer...\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "info: Invalid read pointer...\n");
                return -1;
        }
 
        /* Read the event ring write pointer set by firmware */
        if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
-               dev_err(adapter->dev,
-                       "EventReady: failed to read reg->evt_wrptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "EventReady: failed to read reg->evt_wrptr\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
-               card->evtbd_rdptr, wrptr);
+       mwifiex_dbg(adapter, EVENT,
+                   "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
+                   card->evtbd_rdptr, wrptr);
        if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
                                              & MWIFIEX_EVTBD_MASK)) ||
            ((wrptr & reg->evt_rollover_ind) ==
@@ -1705,7 +1729,8 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
                __le16 data_len = 0;
                u16 evt_len;
 
-               dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: Read Index: %d\n", rdptr);
                skb_cmd = card->evt_buf_list[rdptr];
                mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
 
@@ -1721,9 +1746,10 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
                   len is 2 bytes followed by type which is 2 bytes */
                memcpy(&data_len, skb_cmd->data, sizeof(__le16));
                evt_len = le16_to_cpu(data_len);
-
+               skb_trim(skb_cmd, evt_len);
                skb_pull(skb_cmd, INTF_HEADER_LEN);
-               dev_dbg(adapter->dev, "info: Event length: %d\n", evt_len);
+               mwifiex_dbg(adapter, EVENT,
+                           "info: Event length: %d\n", evt_len);
 
                if ((evt_len > 0) && (evt_len  < MAX_EVENT_SIZE))
                        memcpy(adapter->event_body, skb_cmd->data +
@@ -1740,8 +1766,8 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
        } else {
                if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
                                      CPU_INTR_EVENT_DONE)) {
-                       dev_warn(adapter->dev,
-                                "Write register failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Write register failed\n");
                        return -1;
                }
        }
@@ -1766,15 +1792,16 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
                return 0;
 
        if (rdptr >= MWIFIEX_MAX_EVT_BD) {
-               dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n",
-                       rdptr);
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: Invalid rdptr 0x%x\n",
+                           rdptr);
                return -EINVAL;
        }
 
        /* Read the event ring write pointer set by firmware */
        if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
-               dev_err(adapter->dev,
-                       "event_complete: failed to read reg->evt_wrptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: failed to read reg->evt_wrptr\n");
                return -1;
        }
 
@@ -1791,9 +1818,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
                desc->flags = 0;
                skb = NULL;
        } else {
-               dev_dbg(adapter->dev,
-                       "info: ERROR: buf still valid at index %d, <%p, %p>\n",
-                       rdptr, card->evt_buf_list[rdptr], skb);
+               mwifiex_dbg(adapter, ERROR,
+                           "info: ERROR: buf still valid at index %d, <%p, %p>\n",
+                           rdptr, card->evt_buf_list[rdptr], skb);
        }
 
        if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
@@ -1802,18 +1829,20 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
                                        reg->evt_rollover_ind);
        }
 
-       dev_dbg(adapter->dev, "info: Updated <Rd: 0x%x, Wr: 0x%x>",
-               card->evtbd_rdptr, wrptr);
+       mwifiex_dbg(adapter, EVENT,
+                   "info: Updated <Rd: 0x%x, Wr: 0x%x>",
+                   card->evtbd_rdptr, wrptr);
 
        /* Write the event ring read pointer in to reg->evt_rdptr */
        if (mwifiex_write_reg(adapter, reg->evt_rdptr,
                              card->evtbd_rdptr)) {
-               dev_err(adapter->dev,
-                       "event_complete: failed to read reg->evt_rdptr\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "event_complete: failed to read reg->evt_rdptr\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: Check Events Again\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "info: Check Events Again\n");
        ret = mwifiex_pcie_process_event_ready(adapter);
 
        return ret;
@@ -1840,17 +1869,18 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
        if (!firmware || !firmware_len) {
-               dev_err(adapter->dev,
-                       "No firmware image found! Terminating download\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "No firmware image found! Terminating download\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: Downloading FW image (%d bytes)\n",
-               firmware_len);
+       mwifiex_dbg(adapter, INFO,
+                   "info: Downloading FW image (%d bytes)\n",
+                   firmware_len);
 
        if (mwifiex_pcie_disable_host_int(adapter)) {
-               dev_err(adapter->dev,
-                       "%s: Disabling interrupts failed.\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: Disabling interrupts failed.\n", __func__);
                return -1;
        }
 
@@ -1872,8 +1902,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                        ret = mwifiex_read_reg(adapter, reg->cmd_size,
                                               &len);
                        if (ret) {
-                               dev_warn(adapter->dev,
-                                        "Failed reading len from boot code\n");
+                               mwifiex_dbg(adapter, FATAL,
+                                           "Failed reading len from boot code\n");
                                goto done;
                        }
                        if (len)
@@ -1884,8 +1914,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (!len) {
                        break;
                } else if (len > MWIFIEX_UPLD_SIZE) {
-                       pr_err("FW download failure @ %d, invalid length %d\n",
-                              offset, len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download failure @ %d, invalid length %d\n",
+                                   offset, len);
                        ret = -1;
                        goto done;
                }
@@ -1895,14 +1926,16 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (len & BIT(0)) {
                        block_retry_cnt++;
                        if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
-                               pr_err("FW download failure @ %d, over max "
-                                      "retry count\n", offset);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW download failure @ %d, over max\t"
+                                           "retry count\n", offset);
                                ret = -1;
                                goto done;
                        }
-                       dev_err(adapter->dev, "FW CRC error indicated by the "
-                               "helper: len = 0x%04X, txlen = %d\n",
-                               len, txlen);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW CRC error indicated by the\t"
+                                   "helper: len = 0x%04X, txlen = %d\n",
+                                   len, txlen);
                        len &= ~BIT(0);
                        /* Setting this to 0 to resend from same offset */
                        txlen = 0;
@@ -1913,7 +1946,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                        if (firmware_len - offset < txlen)
                                txlen = firmware_len - offset;
 
-                       dev_dbg(adapter->dev, ".");
+                       mwifiex_dbg(adapter, INFO, ".");
 
                        tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
                                    card->pcie.blksz_fw_dl;
@@ -1927,8 +1960,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 
                /* Send the boot command to device */
                if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
-                       dev_err(adapter->dev,
-                               "Failed to send firmware download command\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to send firmware download command\n");
                        ret = -1;
                        goto done;
                }
@@ -1937,9 +1970,10 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                do {
                        if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
                                             &ireg_intr)) {
-                               dev_err(adapter->dev, "%s: Failed to read "
-                                       "interrupt status during fw dnld.\n",
-                                       __func__);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "%s: Failed to read\t"
+                                           "interrupt status during fw dnld.\n",
+                                           __func__);
                                mwifiex_unmap_pci_memory(adapter, skb,
                                                         PCI_DMA_TODEVICE);
                                ret = -1;
@@ -1953,8 +1987,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                offset += txlen;
        } while (true);
 
-       dev_notice(adapter->dev,
-                  "info: FW download over, size %d bytes\n", offset);
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", offset);
 
        ret = 0;
 
@@ -1980,15 +2014,17 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
        /* Mask spurios interrupts */
        if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
                              HOST_INTR_MASK)) {
-               dev_warn(adapter->dev, "Write register failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Write register failed\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "Setting driver ready signature\n");
+       mwifiex_dbg(adapter, INFO,
+                   "Setting driver ready signature\n");
        if (mwifiex_write_reg(adapter, reg->drv_rdy,
                              FIRMWARE_READY_PCIE)) {
-               dev_err(adapter->dev,
-                       "Failed to write driver ready signature\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Failed to write driver ready signature\n");
                return -1;
        }
 
@@ -2015,12 +2051,13 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
                                     &winner_status))
                        ret = -1;
                else if (!winner_status) {
-                       dev_err(adapter->dev, "PCI-E is the winner\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "PCI-E is the winner\n");
                        adapter->winner = 1;
                } else {
-                       dev_err(adapter->dev,
-                               "PCI-E is not the winner <%#x,%d>, exit dnld\n",
-                               ret, adapter->winner);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "PCI-E is not the winner <%#x,%d>, exit dnld\n",
+                                   ret, adapter->winner);
                }
        }
 
@@ -2039,7 +2076,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                return;
 
        if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
-               dev_warn(adapter->dev, "Read register failed\n");
+               mwifiex_dbg(adapter, ERROR, "Read register failed\n");
                return;
        }
 
@@ -2050,7 +2087,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                /* Clear the pending interrupts */
                if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
                                      ~pcie_ireg)) {
-                       dev_warn(adapter->dev, "Write register failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Write register failed\n");
                        return;
                }
                spin_lock_irqsave(&adapter->int_lock, flags);
@@ -2133,21 +2171,24 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
        while (pcie_ireg & HOST_INTR_MASK) {
                if (pcie_ireg & HOST_INTR_DNLD_DONE) {
                        pcie_ireg &= ~HOST_INTR_DNLD_DONE;
-                       dev_dbg(adapter->dev, "info: TX DNLD Done\n");
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: TX DNLD Done\n");
                        ret = mwifiex_pcie_send_data_complete(adapter);
                        if (ret)
                                return ret;
                }
                if (pcie_ireg & HOST_INTR_UPLD_RDY) {
                        pcie_ireg &= ~HOST_INTR_UPLD_RDY;
-                       dev_dbg(adapter->dev, "info: Rx DATA\n");
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: Rx DATA\n");
                        ret = mwifiex_pcie_process_recv_data(adapter);
                        if (ret)
                                return ret;
                }
                if (pcie_ireg & HOST_INTR_EVENT_RDY) {
                        pcie_ireg &= ~HOST_INTR_EVENT_RDY;
-                       dev_dbg(adapter->dev, "info: Rx EVENT\n");
+                       mwifiex_dbg(adapter, INTR,
+                                   "info: Rx EVENT\n");
                        ret = mwifiex_pcie_process_event_ready(adapter);
                        if (ret)
                                return ret;
@@ -2156,8 +2197,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                if (pcie_ireg & HOST_INTR_CMD_DONE) {
                        pcie_ireg &= ~HOST_INTR_CMD_DONE;
                        if (adapter->cmd_sent) {
-                               dev_dbg(adapter->dev,
-                                       "info: CMD sent Interrupt\n");
+                               mwifiex_dbg(adapter, INTR,
+                                           "info: CMD sent Interrupt\n");
                                adapter->cmd_sent = false;
                        }
                        /* Handle command response */
@@ -2169,8 +2210,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                if (mwifiex_pcie_ok_to_access_hw(adapter)) {
                        if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
                                             &pcie_ireg)) {
-                               dev_warn(adapter->dev,
-                                        "Read register failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "Read register failed\n");
                                return -1;
                        }
 
@@ -2178,16 +2219,17 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                                if (mwifiex_write_reg(adapter,
                                                      PCIE_HOST_INT_STATUS,
                                                      ~pcie_ireg)) {
-                                       dev_warn(adapter->dev,
-                                                "Write register failed\n");
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Write register failed\n");
                                        return -1;
                                }
                        }
 
                }
        }
-       dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
-               adapter->cmd_sent, adapter->data_sent);
+       mwifiex_dbg(adapter, INTR,
+                   "info: cmd_sent=%d data_sent=%d\n",
+                   adapter->cmd_sent, adapter->data_sent);
        if (adapter->ps_state != PS_STATE_SLEEP)
                mwifiex_pcie_enable_host_int(adapter);
 
@@ -2209,7 +2251,8 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
                                     struct mwifiex_tx_param *tx_param)
 {
        if (!skb) {
-               dev_err(adapter->dev, "Passed NULL skb to %s\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "Passed NULL skb to %s\n", __func__);
                return -1;
        }
 
@@ -2232,7 +2275,8 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
 
        ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
        if (ret) {
-               dev_err(adapter->dev, "PCIE write err\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "PCIE write err\n");
                return RDWR_STATUS_FAILURE;
        }
 
@@ -2243,24 +2287,25 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
                if (doneflag && ctrl_data == doneflag)
                        return RDWR_STATUS_DONE;
                if (ctrl_data != FW_DUMP_HOST_READY) {
-                       dev_info(adapter->dev,
-                                "The ctrl reg was changed, re-try again!\n");
+                       mwifiex_dbg(adapter, WARN,
+                                   "The ctrl reg was changed, re-try again!\n");
                        ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
                                                FW_DUMP_HOST_READY);
                        if (ret) {
-                               dev_err(adapter->dev, "PCIE write err\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "PCIE write err\n");
                                return RDWR_STATUS_FAILURE;
                        }
                }
                usleep_range(100, 200);
        }
 
-       dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+       mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
        return RDWR_STATUS_FAILURE;
 }
 
 /* This function dump firmware memory to file */
-static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
+static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
        const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
@@ -2269,7 +2314,6 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
        enum rdwr_status stat;
        u32 memory_size;
        int ret;
-       static char *env[] = { "DRIVER=mwifiex_pcie", "EVENT=fw_dump", NULL };
 
        if (!card->pcie.can_dump_fw)
                return;
@@ -2284,12 +2328,12 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
                entry->mem_size = 0;
        }
 
-       dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
 
        /* Read the number of the memories which will dump */
        stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
        if (stat == RDWR_STATUS_FAILURE)
-               goto done;
+               return;
 
        reg = creg->fw_dump_start;
        mwifiex_read_reg_byte(adapter, reg, &dump_num);
@@ -2300,7 +2344,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
 
                stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
                if (stat == RDWR_STATUS_FAILURE)
-                       goto done;
+                       return;
 
                memory_size = 0;
                reg = creg->fw_dump_start;
@@ -2311,36 +2355,36 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
                }
 
                if (memory_size == 0) {
-                       dev_info(adapter->dev, "Firmware dump Finished!\n");
+                       mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
                        ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
                                                FW_DUMP_READ_DONE);
                        if (ret) {
-                               dev_err(adapter->dev, "PCIE write err\n");
-                               goto done;
+                               mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
+                               return;
                        }
                        break;
                }
 
-               dev_info(adapter->dev,
-                        "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+               mwifiex_dbg(adapter, DUMP,
+                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
                entry->mem_ptr = vmalloc(memory_size + 1);
                entry->mem_size = memory_size;
                if (!entry->mem_ptr) {
-                       dev_err(adapter->dev,
-                               "Vmalloc %s failed\n", entry->mem_name);
-                       goto done;
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Vmalloc %s failed\n", entry->mem_name);
+                       return;
                }
                dbg_ptr = entry->mem_ptr;
                end_ptr = dbg_ptr + memory_size;
 
                doneflag = entry->done_flag;
-               dev_info(adapter->dev, "Start %s output, please wait...\n",
-                        entry->mem_name);
+               mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
+                           entry->mem_name);
 
                do {
                        stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
                        if (RDWR_STATUS_FAILURE == stat)
-                               goto done;
+                               return;
 
                        reg_start = creg->fw_dump_start;
                        reg_end = creg->fw_dump_end;
@@ -2349,46 +2393,49 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
                                if (dbg_ptr < end_ptr) {
                                        dbg_ptr++;
                                } else {
-                                       dev_err(adapter->dev,
-                                               "Allocated buf not enough\n");
-                                       goto done;
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Allocated buf not enough\n");
+                                       return;
                                }
                        }
 
                        if (stat != RDWR_STATUS_DONE)
                                continue;
 
-                       dev_info(adapter->dev, "%s done: size=0x%tx\n",
-                                entry->mem_name, dbg_ptr - entry->mem_ptr);
+                       mwifiex_dbg(adapter, DUMP,
+                                   "%s done: size=0x%tx\n",
+                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
                        break;
                } while (true);
        }
-       dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
-
-       kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+       mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
+}
 
-done:
-       adapter->curr_mem_idx = 0;
+static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
+{
+       mwifiex_drv_info_dump(adapter);
+       mwifiex_pcie_fw_dump(adapter);
+       mwifiex_upload_device_dump(adapter);
 }
 
 static unsigned long iface_work_flags;
 static struct mwifiex_adapter *save_adapter;
 static void mwifiex_pcie_work(struct work_struct *work)
 {
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
                               &iface_work_flags))
-               mwifiex_pcie_fw_dump_work(save_adapter);
+               mwifiex_pcie_device_dump_work(save_adapter);
 }
 
 static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
 /* This function dumps FW information */
-static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
+static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
 {
        save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags))
+       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
                return;
 
-       set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags);
+       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
 
        schedule_work(&pcie_work);
 }
@@ -2418,45 +2465,50 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
 
        pci_set_master(pdev);
 
-       dev_dbg(adapter->dev, "try set_consistent_dma_mask(32)\n");
+       mwifiex_dbg(adapter, INFO,
+                   "try set_consistent_dma_mask(32)\n");
        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               dev_err(adapter->dev, "set_dma_mask(32) failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "set_dma_mask(32) failed\n");
                goto err_set_dma_mask;
        }
 
        ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               dev_err(adapter->dev, "set_consistent_dma_mask(64) failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "set_consistent_dma_mask(64) failed\n");
                goto err_set_dma_mask;
        }
 
        ret = pci_request_region(pdev, 0, DRV_NAME);
        if (ret) {
-               dev_err(adapter->dev, "req_reg(0) error\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "req_reg(0) error\n");
                goto err_req_region0;
        }
        card->pci_mmap = pci_iomap(pdev, 0, 0);
        if (!card->pci_mmap) {
-               dev_err(adapter->dev, "iomap(0) error\n");
+               mwifiex_dbg(adapter, ERROR, "iomap(0) error\n");
                ret = -EIO;
                goto err_iomap0;
        }
        ret = pci_request_region(pdev, 2, DRV_NAME);
        if (ret) {
-               dev_err(adapter->dev, "req_reg(2) error\n");
+               mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n");
                goto err_req_region2;
        }
        card->pci_mmap1 = pci_iomap(pdev, 2, 0);
        if (!card->pci_mmap1) {
-               dev_err(adapter->dev, "iomap(2) error\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "iomap(2) error\n");
                ret = -EIO;
                goto err_iomap2;
        }
 
-       dev_dbg(adapter->dev,
-               "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
-               card->pci_mmap, card->pci_mmap1);
+       mwifiex_dbg(adapter, INFO,
+                   "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
+                   card->pci_mmap, card->pci_mmap1);
 
        card->cmdrsp_buf = NULL;
        ret = mwifiex_pcie_create_txbd_ring(adapter);
@@ -2521,10 +2573,11 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
        if (user_rmmod) {
-               dev_dbg(adapter->dev, "Clearing driver ready signature\n");
+               mwifiex_dbg(adapter, INFO,
+                           "Clearing driver ready signature\n");
                if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
-                       dev_err(adapter->dev,
-                               "Failed to write driver not-ready signature\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Failed to write driver not-ready signature\n");
        }
 
        if (pdev) {
@@ -2555,7 +2608,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
                          "MRVL_PCIE", pdev);
        if (ret) {
-               pr_err("request_irq failed: ret=%d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "request_irq failed: ret=%d\n", ret);
                adapter->card = NULL;
                return -1;
        }
@@ -2582,7 +2636,8 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
        const struct mwifiex_pcie_card_reg *reg;
 
        if (card) {
-               dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "%s(): calling free_irq()\n", __func__);
                free_irq(card->dev->irq, card->dev);
 
                reg = card->pcie.reg;
@@ -2617,7 +2672,7 @@ static struct mwifiex_if_ops pcie_ops = {
        .cleanup_mpa_buf =              NULL,
        .init_fw_port =                 mwifiex_pcie_init_fw_port,
        .clean_pcie_ring =              mwifiex_clean_pcie_ring_buf,
-       .fw_dump =                      mwifiex_pcie_fw_dump,
+       .device_dump =                  mwifiex_pcie_device_dump,
 };
 
 /*
index 0ffdb7c5afd21345cfea5c025d0a2cacb2840076..baf9715ddc1034bc58e6ec4cea367caa670b571c 100644 (file)
@@ -241,20 +241,21 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
            * LinkSys WRT54G && bss_desc->privacy
            */
         ) {
-               dev_dbg(priv->adapter->dev, "info: %s: WPA:"
-                       " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
-                       "EncMode=%#x privacy=%#x\n", __func__,
-                       (bss_desc->bcn_wpa_ie) ?
-                       (*(bss_desc->bcn_wpa_ie)).
-                       vend_hdr.element_id : 0,
-                       (bss_desc->bcn_rsn_ie) ?
-                       (*(bss_desc->bcn_rsn_ie)).
-                       ieee_hdr.element_id : 0,
-                       (priv->sec_info.wep_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                       priv->sec_info.encryption_mode,
-                       bss_desc->privacy);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: WPA:\t"
+                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
+                           "EncMode=%#x privacy=%#x\n", __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
                return true;
        }
        return false;
@@ -277,20 +278,21 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
                 * Privacy bit may NOT be set in some APs like
                 * LinkSys WRT54G && bss_desc->privacy
                 */
-               dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
-                       " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
-                       "EncMode=%#x privacy=%#x\n", __func__,
-                       (bss_desc->bcn_wpa_ie) ?
-                       (*(bss_desc->bcn_wpa_ie)).
-                       vend_hdr.element_id : 0,
-                       (bss_desc->bcn_rsn_ie) ?
-                       (*(bss_desc->bcn_rsn_ie)).
-                       ieee_hdr.element_id : 0,
-                       (priv->sec_info.wep_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                       priv->sec_info.encryption_mode,
-                       bss_desc->privacy);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: WPA2:\t"
+                           "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
+                           "EncMode=%#x privacy=%#x\n", __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
                return true;
        }
        return false;
@@ -333,18 +335,19 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
            ((!bss_desc->bcn_rsn_ie) ||
             ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
            priv->sec_info.encryption_mode && bss_desc->privacy) {
-               dev_dbg(priv->adapter->dev, "info: %s: dynamic "
-                       "WEP: wpa_ie=%#x wpa2_ie=%#x "
-                       "EncMode=%#x privacy=%#x\n",
-                       __func__,
-                       (bss_desc->bcn_wpa_ie) ?
-                       (*(bss_desc->bcn_wpa_ie)).
-                       vend_hdr.element_id : 0,
-                       (bss_desc->bcn_rsn_ie) ?
-                       (*(bss_desc->bcn_rsn_ie)).
-                       ieee_hdr.element_id : 0,
-                       priv->sec_info.encryption_mode,
-                       bss_desc->privacy);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: %s: dynamic\t"
+                           "WEP: wpa_ie=%#x wpa2_ie=%#x\t"
+                           "EncMode=%#x privacy=%#x\n",
+                           __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).
+                           vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).
+                           ieee_hdr.element_id : 0,
+                           priv->sec_info.encryption_mode,
+                           bss_desc->privacy);
                return true;
        }
        return false;
@@ -383,19 +386,20 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
                return 0;
 
        if (priv->wps.session_enable) {
-               dev_dbg(adapter->dev,
-                       "info: return success directly in WPS period\n");
+               mwifiex_dbg(adapter, IOCTL,
+                           "info: return success directly in WPS period\n");
                return 0;
        }
 
        if (bss_desc->chan_sw_ie_present) {
-               dev_err(adapter->dev,
-                       "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
+               mwifiex_dbg(adapter, INFO,
+                           "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
                return -1;
        }
 
        if (mwifiex_is_bss_wapi(priv, bss_desc)) {
-               dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: return success for WAPI AP\n");
                return 0;
        }
 
@@ -405,7 +409,8 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
                        return 0;
                } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
                        /* Static WEP enabled */
-                       dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Disable 11n in WEP mode.\n");
                        bss_desc->disable_11n = true;
                        return 0;
                } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
@@ -418,9 +423,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
 
                                if (mwifiex_is_wpa_oui_present
                                                (bss_desc, CIPHER_SUITE_TKIP)) {
-                                       dev_dbg(adapter->dev,
-                                               "info: Disable 11n if AES "
-                                               "is not supported by AP\n");
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Disable 11n if AES\t"
+                                                   "is not supported by AP\n");
                                        bss_desc->disable_11n = true;
                                } else {
                                        return -1;
@@ -437,9 +442,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
 
                                if (mwifiex_is_rsn_oui_present
                                                (bss_desc, CIPHER_SUITE_TKIP)) {
-                                       dev_dbg(adapter->dev,
-                                               "info: Disable 11n if AES "
-                                               "is not supported by AP\n");
+                                       mwifiex_dbg(adapter, INFO,
+                                                   "info: Disable 11n if AES\t"
+                                                   "is not supported by AP\n");
                                        bss_desc->disable_11n = true;
                                } else {
                                        return -1;
@@ -455,17 +460,18 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
                }
 
                /* Security doesn't match */
-               dev_dbg(adapter->dev,
-                       "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s "
-                       "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", __func__,
-                       (bss_desc->bcn_wpa_ie) ?
-                       (*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id : 0,
-                       (bss_desc->bcn_rsn_ie) ?
-                       (*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id : 0,
-                       (priv->sec_info.wep_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa_enabled) ? "e" : "d",
-                       (priv->sec_info.wpa2_enabled) ? "e" : "d",
-                       priv->sec_info.encryption_mode, bss_desc->privacy);
+               mwifiex_dbg(adapter, ERROR,
+                           "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t"
+                           "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
+                           __func__,
+                           (bss_desc->bcn_wpa_ie) ?
+                           (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0,
+                           (bss_desc->bcn_rsn_ie) ?
+                           (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0,
+                           (priv->sec_info.wep_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa_enabled) ? "e" : "d",
+                           (priv->sec_info.wpa2_enabled) ? "e" : "d",
+                           priv->sec_info.encryption_mode, bss_desc->privacy);
                return -1;
        }
 
@@ -560,7 +566,8 @@ mwifiex_append_rate_tlv(struct mwifiex_private *priv,
        else
                rates_size = mwifiex_get_supported_rates(priv, rates);
 
-       dev_dbg(priv->adapter->dev, "info: SCAN_CMD: Rates size = %d\n",
+       mwifiex_dbg(priv->adapter, CMD,
+                   "info: SCAN_CMD: Rates size = %d\n",
                rates_size);
        rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
        rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
@@ -600,9 +607,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
        u8 radio_type;
 
        if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
-               dev_dbg(priv->adapter->dev,
-                       "info: Scan: Null detect: %p, %p, %p\n",
-                      scan_cfg_out, chan_tlv_out, scan_chan_list);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "info: Scan: Null detect: %p, %p, %p\n",
+                           scan_cfg_out, chan_tlv_out, scan_chan_list);
                return -1;
        }
 
@@ -645,16 +652,16 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
                        }
 
                        radio_type = tmp_chan_list->radio_type;
-                       dev_dbg(priv->adapter->dev,
-                               "info: Scan: Chan(%3d), Radio(%d),"
-                               Mode(%d, %d), Dur(%d)\n",
-                               tmp_chan_list->chan_number,
-                               tmp_chan_list->radio_type,
-                               tmp_chan_list->chan_scan_mode_bitmap
-                               & MWIFIEX_PASSIVE_SCAN,
-                               (tmp_chan_list->chan_scan_mode_bitmap
-                                & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
-                               le16_to_cpu(tmp_chan_list->max_scan_time));
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Scan: Chan(%3d), Radio(%d),\t"
+                                   "Mode(%d, %d), Dur(%d)\n",
+                                   tmp_chan_list->chan_number,
+                                   tmp_chan_list->radio_type,
+                                   tmp_chan_list->chan_scan_mode_bitmap
+                                   & MWIFIEX_PASSIVE_SCAN,
+                                   (tmp_chan_list->chan_scan_mode_bitmap
+                                   & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
+                                   le16_to_cpu(tmp_chan_list->max_scan_time));
 
                        /* Copy the current channel TLV to the command being
                           prepared */
@@ -718,9 +725,11 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
                /* The total scan time should be less than scan command timeout
                   value */
                if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
-                       dev_err(priv->adapter->dev, "total scan time %dms"
-                               " is over limit (%dms), scan skipped\n",
-                               total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "total scan time %dms\t"
+                                   "is over limit (%dms), scan skipped\n",
+                                   total_scan_time,
+                                   MWIFIEX_MAX_TOTAL_SCAN_TIME);
                        ret = -1;
                        break;
                }
@@ -905,9 +914,10 @@ mwifiex_config_scan(struct mwifiex_private *priv,
                        tlv_pos += (sizeof(wildcard_ssid_tlv->header)
                                + le16_to_cpu(wildcard_ssid_tlv->header.len));
 
-                       dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n",
-                               i, wildcard_ssid_tlv->ssid,
-                               wildcard_ssid_tlv->max_ssid_length);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan: ssid[%d]: %s, %d\n",
+                                   i, wildcard_ssid_tlv->ssid,
+                                   wildcard_ssid_tlv->max_ssid_length);
 
                        /* Empty wildcard ssid with a maxlen will match many or
                           potentially all SSIDs (maxlen == 32), therefore do
@@ -928,8 +938,9 @@ mwifiex_config_scan(struct mwifiex_private *priv,
                        *filtered_scan = true;
 
                if (user_scan_in->scan_chan_gap) {
-                       dev_dbg(adapter->dev, "info: scan: channel gap = %d\n",
-                               user_scan_in->scan_chan_gap);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan: channel gap = %d\n",
+                                   user_scan_in->scan_chan_gap);
                        *max_chan_per_scan =
                                        MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
 
@@ -961,8 +972,9 @@ mwifiex_config_scan(struct mwifiex_private *priv,
           add tlv */
        if (num_probes) {
 
-               dev_dbg(adapter->dev, "info: scan: num_probes = %d\n",
-                       num_probes);
+               mwifiex_dbg(adapter, INFO,
+                           "info: scan: num_probes = %d\n",
+                           num_probes);
 
                num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
                num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
@@ -1003,7 +1015,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 
        if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
 
-               dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: Scan: Using supplied channel list\n");
 
                for (chan_idx = 0;
                     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
@@ -1056,13 +1069,13 @@ mwifiex_config_scan(struct mwifiex_private *priv,
                    (user_scan_in->chan_list[0].chan_number ==
                     priv->curr_bss_params.bss_descriptor.channel)) {
                        *scan_current_only = true;
-                       dev_dbg(adapter->dev,
-                               "info: Scan: Scanning current channel only\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Scan: Scanning current channel only\n");
                }
                chan_num = chan_idx;
        } else {
-               dev_dbg(adapter->dev,
-                       "info: Scan: Creating full region channel list\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: Scan: Creating full region channel list\n");
                chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
                                                            scan_chan_list,
                                                            *filtered_scan);
@@ -1094,8 +1107,9 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
        tlv_buf_left = tlv_buf_size;
        *tlv_data = NULL;
 
-       dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n",
-               tlv_buf_size);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: tlv_buf_size = %d\n",
+                   tlv_buf_size);
 
        while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
 
@@ -1103,26 +1117,31 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
                tlv_len = le16_to_cpu(current_tlv->header.len);
 
                if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
-                       dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "SCAN_RESP: TLV buffer corrupt\n");
                        break;
                }
 
                if (req_tlv_type == tlv_type) {
                        switch (tlv_type) {
                        case TLV_TYPE_TSFTIMESTAMP:
-                               dev_dbg(adapter->dev, "info: SCAN_RESP: TSF "
-                                       "timestamp TLV, len = %d\n", tlv_len);
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: SCAN_RESP: TSF\t"
+                                           "timestamp TLV, len = %d\n",
+                                           tlv_len);
                                *tlv_data = current_tlv;
                                break;
                        case TLV_TYPE_CHANNELBANDLIST:
-                               dev_dbg(adapter->dev, "info: SCAN_RESP: channel"
-                                       " band list TLV, len = %d\n", tlv_len);
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: SCAN_RESP: channel\t"
+                                           "band list TLV, len = %d\n",
+                                           tlv_len);
                                *tlv_data = current_tlv;
                                break;
                        default:
-                               dev_err(adapter->dev,
-                                       "SCAN_RESP: unhandled TLV = %d\n",
-                                      tlv_type);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SCAN_RESP: unhandled TLV = %d\n",
+                                           tlv_type);
                                /* Give up, this seems corrupted */
                                return;
                        }
@@ -1177,8 +1196,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                total_ie_len = element_len + sizeof(struct ieee_types_header);
 
                if (bytes_left < total_ie_len) {
-                       dev_err(adapter->dev, "err: InterpretIE: in processing"
-                               " IE, bytes left < IE length\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "err: InterpretIE: in processing\t"
+                                   "IE, bytes left < IE length\n");
                        return -1;
                }
                switch (element_id) {
@@ -1186,9 +1206,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        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);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: InterpretIE: ssid: %-32s\n",
+                                   bss_entry->ssid.ssid);
                        break;
 
                case WLAN_EID_SUPP_RATES:
@@ -1419,19 +1439,20 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
        unsigned long flags;
 
        if (adapter->scan_processing) {
-               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan already in process...\n");
                return -EBUSY;
        }
 
        if (priv->scan_block) {
-               dev_err(adapter->dev,
-                       "cmd: Scan is blocked during association...\n");
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan is blocked during association...\n");
                return -EBUSY;
        }
 
        if (adapter->surprise_removed || adapter->is_cmd_timedout) {
-               dev_err(adapter->dev,
-                       "Ignore scan. Card removed or firmware in bad state\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Ignore scan. Card removed or firmware in bad state\n");
                return -EFAULT;
        }
 
@@ -1478,7 +1499,8 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
 
                        /* Perform internal scan synchronously */
                        if (!priv->scan_request) {
-                               dev_dbg(adapter->dev, "wait internal scan\n");
+                               mwifiex_dbg(adapter, INFO,
+                                           "wait internal scan\n");
                                mwifiex_wait_queue_complete(adapter, cmd_node);
                        }
                } else {
@@ -1553,8 +1575,8 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
                        ret = mwifiex_is_network_compatible(priv, bss_desc,
                                                            priv->bss_mode);
                        if (ret)
-                               dev_err(priv->adapter->dev,
-                                       "Incompatible network settings\n");
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "Incompatible network settings\n");
                        break;
                default:
                        ret = 0;
@@ -1656,7 +1678,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
         */
        if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
            sizeof(struct mwifiex_fixed_bcn_param)) {
-               dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "InterpretIE: not enough bytes left\n");
                return -EFAULT;
        }
 
@@ -1669,7 +1692,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
                rssi = (-rssi) * 100;           /* Convert dBm to mBm */
                current_ptr += sizeof(u8);
                curr_bcn_bytes -= sizeof(u8);
-               dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
+               mwifiex_dbg(adapter, INFO,
+                           "info: InterpretIE: RSSI=%d\n", rssi);
        } else {
                rssi = rssi_val;
        }
@@ -1682,14 +1706,16 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
        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);
+       mwifiex_dbg(adapter, INFO,
+                   "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);
+       mwifiex_dbg(adapter, INFO,
+                   "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;
@@ -1698,8 +1724,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
                element_len = *(current_ptr + 1);
                if (curr_bcn_bytes < element_len +
                                sizeof(struct ieee_types_header)) {
-                       dev_err(adapter->dev,
-                               "%s: bytes left < IE length\n", __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: bytes left < IE length\n", __func__);
                        return -EFAULT;
                }
                if (element_id == WLAN_EID_DS_PARAMS) {
@@ -1719,8 +1745,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
 
                /* Skip entry if on csa closed channel */
                if (channel == priv->csa_chan) {
-                       dev_dbg(adapter->dev,
-                               "Dropping entry on csa closed channel\n");
+                       mwifiex_dbg(adapter, WARN,
+                                   "Dropping entry on csa closed channel\n");
                        return 0;
                }
 
@@ -1751,7 +1777,7 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
                        cfg80211_put_bss(priv->wdev.wiphy, bss);
                }
        } else {
-               dev_dbg(adapter->dev, "missing BSS channel IE\n");
+               mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
        }
 
        return 0;
@@ -1765,7 +1791,8 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
        if (adapter->curr_cmd->wait_q_enabled) {
                adapter->cmd_wait_q.status = 0;
                if (!priv->scan_request) {
-                       dev_dbg(adapter->dev, "complete internal scan\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "complete internal scan\n");
                        mwifiex_complete_cmd(adapter, adapter->curr_cmd);
                }
        }
@@ -1788,12 +1815,14 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
                        mwifiex_complete_scan(priv);
 
                if (priv->scan_request) {
-                       dev_dbg(adapter->dev, "info: notifying scan done\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: notifying scan done\n");
                        cfg80211_scan_done(priv->scan_request, 0);
                        priv->scan_request = NULL;
                } else {
                        priv->scan_aborting = false;
-                       dev_dbg(adapter->dev, "info: scan already aborted\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan already aborted\n");
                }
        } else if ((priv->scan_aborting && !priv->scan_request) ||
                   priv->scan_block) {
@@ -1809,12 +1838,14 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 
                if (priv->scan_request) {
-                       dev_dbg(adapter->dev, "info: aborting scan\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: aborting scan\n");
                        cfg80211_scan_done(priv->scan_request, 1);
                        priv->scan_request = NULL;
                } else {
                        priv->scan_aborting = false;
-                       dev_dbg(adapter->dev, "info: scan already aborted\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: scan already aborted\n");
                }
        } else {
                /* Get scan command from scan_pending_q and put to
@@ -1877,8 +1908,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 
 
        if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
-               dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
-                       scan_rsp->number_of_sets);
+               mwifiex_dbg(adapter, ERROR,
+                           "SCAN_RESP: too many AP returned (%d)\n",
+                           scan_rsp->number_of_sets);
                ret = -1;
                goto check_next_scan;
        }
@@ -1887,14 +1919,15 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
        mwifiex_11h_get_csa_closed_channel(priv);
 
        bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
-       dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
-               bytes_left);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: bss_descript_size %d\n",
+                   bytes_left);
 
        scan_resp_size = le16_to_cpu(resp->size);
 
-       dev_dbg(adapter->dev,
-               "info: SCAN_RESP: returned %d APs before parsing\n",
-               scan_rsp->number_of_sets);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SCAN_RESP: returned %d APs before parsing\n",
+                   scan_rsp->number_of_sets);
 
        bss_info = scan_rsp->bss_desc_and_tlv_buffer;
 
@@ -2007,13 +2040,13 @@ mwifiex_update_chan_statistics(struct mwifiex_private *priv,
                                       le16_to_cpu(fw_chan_stats->cca_scan_dur);
                chan_stats.cca_busy_dur =
                                       le16_to_cpu(fw_chan_stats->cca_busy_dur);
-               dev_dbg(adapter->dev,
-                       "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
-                       chan_stats.chan_num,
-                       chan_stats.noise,
-                       chan_stats.total_bss,
-                       chan_stats.cca_scan_dur,
-                       chan_stats.cca_busy_dur);
+               mwifiex_dbg(adapter, INFO,
+                           "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
+                           chan_stats.chan_num,
+                           chan_stats.noise,
+                           chan_stats.total_bss,
+                           chan_stats.cca_scan_dur,
+                           chan_stats.cca_busy_dur);
                memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
                       sizeof(struct mwifiex_chan_stats));
                fw_chan_stats++;
@@ -2035,7 +2068,7 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
        unsigned long cmd_flags, scan_flags;
        bool complete_scan = false;
 
-       dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
+       mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
 
        ext_scan_resp = &resp->params.ext_scan;
 
@@ -2048,8 +2081,8 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
                len = le16_to_cpu(tlv->len);
 
                if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
-                       dev_err(adapter->dev,
-                               "error processing scan response TLVs");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "error processing scan response TLVs");
                        break;
                }
 
@@ -2075,8 +2108,8 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
                        cmd_ptr = (void *)cmd_node->cmd_skb->data;
                        if (le16_to_cpu(cmd_ptr->command) ==
                            HostCmd_CMD_802_11_SCAN_EXT) {
-                               dev_dbg(priv->adapter->dev,
-                                       "Scan pending in command pending list");
+                               mwifiex_dbg(adapter, INFO,
+                                           "Scan pending in command pending list");
                                complete_scan = false;
                                break;
                        }
@@ -2114,17 +2147,20 @@ int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
        u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
 
        if (num_of_set > MWIFIEX_MAX_AP) {
-               dev_err(adapter->dev,
-                       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
-                       num_of_set);
+               mwifiex_dbg(adapter, ERROR,
+                           "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+                           num_of_set);
                ret = -1;
                goto check_next_scan;
        }
 
        bytes_left = scan_resp_size;
-       dev_dbg(adapter->dev,
-               "EXT_SCAN: size %d, returned %d APs...",
-               scan_resp_size, num_of_set);
+       mwifiex_dbg(adapter, INFO,
+                   "EXT_SCAN: size %d, returned %d APs...",
+                   scan_resp_size, num_of_set);
+       mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
+                        scan_resp_size +
+                        sizeof(struct mwifiex_event_scan_result));
 
        tlv = (struct mwifiex_ie_types_data *)scan_resp;
 
@@ -2132,7 +2168,8 @@ int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
                type = le16_to_cpu(tlv->header.type);
                len = le16_to_cpu(tlv->header.len);
                if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
-                       dev_err(adapter->dev, "EXT_SCAN: Error bytes left < TLV length\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "EXT_SCAN: Error bytes left < TLV length\n");
                        break;
                }
                scan_rsp_tlv = NULL;
@@ -2158,8 +2195,9 @@ int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
                        len = le16_to_cpu(tlv->header.len);
                        if (bytes_left_for_tlv <
                            sizeof(struct mwifiex_ie_types_header) + len) {
-                               dev_err(adapter->dev,
-                                       "EXT_SCAN: Error in processing TLV, bytes left < TLV length\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EXT_SCAN: Error in processing TLV,\t"
+                                           "bytes left < TLV length\n");
                                scan_rsp_tlv = NULL;
                                bytes_left_for_tlv = 0;
                                continue;
@@ -2199,8 +2237,8 @@ int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
                if (scan_info_tlv) {
                        rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
                        rssi *= 100;           /* Convert dBm to mBm */
-                       dev_dbg(adapter->dev,
-                               "info: InterpretIE: RSSI=%d\n", rssi);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: InterpretIE: RSSI=%d\n", rssi);
                        fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
                        radio_type = &scan_info_tlv->radio_type;
                } else {
@@ -2271,13 +2309,14 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
        struct mwifiex_user_scan_cfg *scan_cfg;
 
        if (adapter->scan_processing) {
-               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan already in process...\n");
                return -EBUSY;
        }
 
        if (priv->scan_block) {
-               dev_err(adapter->dev,
-                       "cmd: Scan is blocked during association...\n");
+               mwifiex_dbg(adapter, WARN,
+                           "cmd: Scan is blocked during association...\n");
                return -EBUSY;
        }
 
@@ -2309,8 +2348,9 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
        int ret;
 
        if (down_interruptible(&priv->async_sem)) {
-               dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
-                       __func__);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "%s: acquire semaphore fail\n",
+                           __func__);
                return -1;
        }
 
@@ -2400,8 +2440,9 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
 
        memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
               curr_bss->beacon_buf_size);
-       dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
-               priv->curr_bcn_size);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: current beacon saved %d\n",
+                   priv->curr_bcn_size);
 
        curr_bss->beacon_buf = priv->curr_bcn_buf;
 
index d10320f89bc16f0f87604fa3840a4a0b72e2530d..a0b121f3460c871eefca6fd30d79a3217ef401c8 100644 (file)
@@ -166,7 +166,8 @@ static int mwifiex_sdio_resume(struct device *dev)
        adapter = card->adapter;
 
        if (!adapter->is_suspended) {
-               dev_warn(adapter->dev, "device already resumed\n");
+               mwifiex_dbg(adapter, WARN,
+                           "device already resumed\n");
                return 0;
        }
 
@@ -191,8 +192,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
        struct mwifiex_adapter *adapter;
        struct mwifiex_private *priv;
 
-       pr_debug("info: SDIO func num=%d\n", func->num);
-
        card = sdio_get_drvdata(func);
        if (!card)
                return;
@@ -201,6 +200,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
        if (!adapter || !adapter->priv_num)
                return;
 
+       mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
+
        if (user_rmmod) {
                if (adapter->is_suspended)
                        mwifiex_sdio_resume(adapter->dev);
@@ -257,12 +258,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
 
        /* Enable the Host Sleep */
        if (!mwifiex_enable_hs(adapter)) {
-               dev_err(adapter->dev, "cmd: failed to suspend\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd: failed to suspend\n");
                adapter->hs_enabling = false;
                return -EFAULT;
        }
 
-       dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       mwifiex_dbg(adapter, INFO,
+                   "cmd: suspend with MMC_PM_KEEP_POWER\n");
        ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
 
        /* Indicate device suspended */
@@ -386,8 +389,8 @@ mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
        u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
 
        if (adapter->is_suspended) {
-               dev_err(adapter->dev,
-                       "%s: not allowed while suspended\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: not allowed while suspended\n", __func__);
                return -1;
        }
 
@@ -434,7 +437,8 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
  */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "event: wakeup device...\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "event: wakeup device...\n");
 
        return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
 }
@@ -446,7 +450,8 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "cmd: wakeup device completed\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "cmd: wakeup device completed\n");
 
        return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
 }
@@ -524,7 +529,8 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
        else
                return -1;
 cont:
-       pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
 
        /* Set Host interrupt reset to read to clear */
        if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, &reg))
@@ -556,10 +562,12 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
                ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);
                if (ret) {
                        i++;
-                       dev_err(adapter->dev, "host_to_card, write iomem"
-                                       " (%d) failed: %d\n", i, ret);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "host_to_card, write iomem\t"
+                                   "(%d) failed: %d\n", i, ret);
                        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               dev_err(adapter->dev, "write CFG reg failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
 
                        ret = -1;
                        if (i > MAX_WRITE_IOMEM_RETRY)
@@ -584,7 +592,8 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
        const struct mwifiex_sdio_card_reg *reg = card->reg;
        u32 rd_bitmap = card->mp_rd_bitmap;
 
-       dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
 
        if (card->supports_sdio_new_mode) {
                if (!(rd_bitmap & reg->data_port_mask))
@@ -598,8 +607,9 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
            (card->mp_rd_bitmap & CTRL_PORT_MASK)) {
                card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK);
                *port = CTRL_PORT;
-               dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n",
-                       *port, card->mp_rd_bitmap);
+               mwifiex_dbg(adapter, DATA,
+                           "data: port=%d mp_rd_bitmap=0x%08x\n",
+                           *port, card->mp_rd_bitmap);
                return 0;
        }
 
@@ -613,9 +623,9 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
        if (++card->curr_rd_port == card->max_ports)
                card->curr_rd_port = reg->start_rd_port;
 
-       dev_dbg(adapter->dev,
-               "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
-               *port, rd_bitmap, card->mp_rd_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
+                   *port, rd_bitmap, card->mp_rd_bitmap);
 
        return 0;
 }
@@ -633,7 +643,8 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
        const struct mwifiex_sdio_card_reg *reg = card->reg;
        u32 wr_bitmap = card->mp_wr_bitmap;
 
-       dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
 
        if (!(wr_bitmap & card->mp_data_port_mask)) {
                adapter->data_sent = true;
@@ -651,15 +662,16 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
        }
 
        if ((card->has_control_mask) && (*port == CTRL_PORT)) {
-               dev_err(adapter->dev,
-                       "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-                       *port, card->curr_wr_port, wr_bitmap,
-                       card->mp_wr_bitmap);
+               mwifiex_dbg(adapter, ERROR,
+                           "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                           *port, card->curr_wr_port, wr_bitmap,
+                           card->mp_wr_bitmap);
                return -1;
        }
 
-       dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-               *port, wr_bitmap, card->mp_wr_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                   *port, wr_bitmap, card->mp_wr_bitmap);
 
        return 0;
 }
@@ -683,7 +695,8 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
                usleep_range(10, 20);
        }
 
-       dev_err(adapter->dev, "poll card status failed, tries = %d\n", tries);
+       mwifiex_dbg(adapter, ERROR,
+                   "poll card status failed, tries = %d\n", tries);
 
        return -1;
 }
@@ -738,7 +751,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
        if (mwifiex_read_data_sync(adapter, card->mp_regs,
                                   card->reg->max_mp_regs,
                                   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
-               dev_err(adapter->dev, "read mp_regs failed\n");
+               mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
                return;
        }
 
@@ -751,7 +764,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                 *      UP_LD_CMD_PORT_HOST_INT_STATUS
                 * Clear the interrupt status register
                 */
-               dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg);
+               mwifiex_dbg(adapter, INTR,
+                           "int: sdio_ireg = %#x\n", sdio_ireg);
                spin_lock_irqsave(&adapter->int_lock, flags);
                adapter->int_status |= sdio_ireg;
                spin_unlock_irqrestore(&adapter->int_lock, flags);
@@ -802,7 +816,8 @@ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
        /* Request the SDIO IRQ */
        ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
        if (ret) {
-               dev_err(adapter->dev, "claim irq failed: ret=%d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "claim irq failed: ret=%d\n", ret);
                goto out;
        }
 
@@ -810,7 +825,8 @@ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
        ret = mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg,
                                       card->reg->host_int_enable);
        if (ret) {
-               dev_err(adapter->dev, "enable host interrupt failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "enable host interrupt failed\n");
                sdio_release_irq(func);
        }
 
@@ -830,22 +846,25 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
        u32 nb;
 
        if (!buffer) {
-               dev_err(adapter->dev, "%s: buffer is NULL\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: buffer is NULL\n", __func__);
                return -1;
        }
 
        ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);
 
        if (ret) {
-               dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__,
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: read iomem failed: %d\n", __func__,
                        ret);
                return -1;
        }
 
        nb = le16_to_cpu(*(__le16 *) (buffer));
        if (nb > npayload) {
-               dev_err(adapter->dev, "%s: invalid packet, nb=%d npayload=%d\n",
-                       __func__, nb, npayload);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: invalid packet, nb=%d npayload=%d\n",
+                           __func__, nb, npayload);
                return -1;
        }
 
@@ -877,13 +896,14 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
        u32 i = 0;
 
        if (!firmware_len) {
-               dev_err(adapter->dev,
-                       "firmware image not found! Terminating download\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "firmware image not found! Terminating download\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n",
-               firmware_len);
+       mwifiex_dbg(adapter, INFO,
+                   "info: downloading FW image (%d bytes)\n",
+                   firmware_len);
 
        /* Assume that the allocated buffer is 8-byte aligned */
        fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL);
@@ -897,8 +917,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY |
                                                    DN_LD_CARD_RDY);
                if (ret) {
-                       dev_err(adapter->dev, "FW download with helper:"
-                               " poll status timeout @ %d\n", offset);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download with helper:\t"
+                                   "poll status timeout @ %d\n", offset);
                        goto done;
                }
 
@@ -910,19 +931,19 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                        ret = mwifiex_read_reg(adapter, reg->base_0_reg,
                                               &base0);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "dev BASE0 register read failed: "
-                                       "base0=%#04X(%d). Terminating dnld\n",
-                                       base0, base0);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE0 register read failed:\t"
+                                           "base0=%#04X(%d). Terminating dnld\n",
+                                           base0, base0);
                                goto done;
                        }
                        ret = mwifiex_read_reg(adapter, reg->base_1_reg,
                                               &base1);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "dev BASE1 register read failed: "
-                                       "base1=%#04X(%d). Terminating dnld\n",
-                                       base1, base1);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE1 register read failed:\t"
+                                           "base1=%#04X(%d). Terminating dnld\n",
+                                           base1, base1);
                                goto done;
                        }
                        len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff));
@@ -936,9 +957,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (!len) {
                        break;
                } else if (len > MWIFIEX_UPLD_SIZE) {
-                       dev_err(adapter->dev,
-                               "FW dnld failed @ %d, invalid length %d\n",
-                               offset, len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW dnld failed @ %d, invalid length %d\n",
+                                   offset, len);
                        ret = -1;
                        goto done;
                }
@@ -948,14 +969,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (len & BIT(0)) {
                        i++;
                        if (i > MAX_WRITE_IOMEM_RETRY) {
-                               dev_err(adapter->dev,
-                                       "FW dnld failed @ %d, over max retry\n",
-                                       offset);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW dnld failed @ %d, over max retry\n",
+                                           offset);
                                ret = -1;
                                goto done;
                        }
-                       dev_err(adapter->dev, "CRC indicated by the helper:"
-                               " len = 0x%04X, txlen = %d\n", len, txlen);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "CRC indicated by the helper:\t"
+                                   "len = 0x%04X, txlen = %d\n", len, txlen);
                        len &= ~BIT(0);
                        /* Setting this to 0 to resend from same offset */
                        txlen = 0;
@@ -978,11 +1000,12 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                                              MWIFIEX_SDIO_BLOCK_SIZE,
                                              adapter->ioport);
                if (ret) {
-                       dev_err(adapter->dev,
-                               "FW download, write iomem (%d) failed @ %d\n",
-                               i, offset);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download, write iomem (%d) failed @ %d\n",
+                                   i, offset);
                        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               dev_err(adapter->dev, "write CFG reg failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
 
                        ret = -1;
                        goto done;
@@ -991,8 +1014,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                offset += txlen;
        } while (true);
 
-       dev_notice(adapter->dev,
-                  "info: FW download over, size %d bytes\n", offset);
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", offset);
 
        ret = 0;
 done:
@@ -1066,18 +1089,20 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
                blk_num = *(data + BLOCK_NUMBER_OFFSET);
                blk_size = adapter->sdio_rx_block_size * blk_num;
                if (blk_size > total_pkt_len) {
-                       dev_err(adapter->dev, "%s: error in pkt,\t"
-                               "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
-                               __func__, blk_num, blk_size, total_pkt_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in blk_size,\t"
+                                   "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
+                                   __func__, blk_num, blk_size, total_pkt_len);
                        break;
                }
                pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
                pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
                                         2));
                if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
-                       dev_err(adapter->dev, "%s: error in pkt,\t"
-                               "pkt_len=%d, blk_size=%d\n",
-                               __func__, pkt_len, blk_size);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in pkt_len,\t"
+                                   "pkt_len=%d, blk_size=%d\n",
+                                   __func__, pkt_len, blk_size);
                        break;
                }
                skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
@@ -1116,7 +1141,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
 
        switch (upld_typ) {
        case MWIFIEX_TYPE_AGGR_DATA:
-               dev_dbg(adapter->dev, "info: --- Rx: Aggr Data packet ---\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: --- Rx: Aggr Data packet ---\n");
                rx_info = MWIFIEX_SKB_RXCB(skb);
                rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA;
                if (adapter->rx_work_enabled) {
@@ -1130,7 +1156,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_DATA:
-               dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n");
+               mwifiex_dbg(adapter, DATA,
+                           "info: --- Rx: Data packet ---\n");
                if (adapter->rx_work_enabled) {
                        skb_queue_tail(&adapter->rx_data_q, skb);
                        adapter->data_received = true;
@@ -1141,7 +1168,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_CMD:
-               dev_dbg(adapter->dev, "info: --- Rx: Cmd Response ---\n");
+               mwifiex_dbg(adapter, CMD,
+                           "info: --- Rx: Cmd Response ---\n");
                /* take care of curr_cmd = NULL case */
                if (!adapter->curr_cmd) {
                        cmd_buf = adapter->upld_buf;
@@ -1163,7 +1191,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_EVENT:
-               dev_dbg(adapter->dev, "info: --- Rx: Event ---\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "info: --- Rx: Event ---\n");
                adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data);
 
                if ((skb->len > 0) && (skb->len  < MAX_EVENT_SIZE))
@@ -1178,7 +1207,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        default:
-               dev_err(adapter->dev, "unknown upload type %#x\n", upld_typ);
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown upload type %#x\n", upld_typ);
                dev_kfree_skb_any(skb);
                break;
        }
@@ -1210,16 +1240,18 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        if ((card->has_control_mask) && (port == CTRL_PORT)) {
                /* Read the command Resp without aggr */
-               dev_dbg(adapter->dev, "info: %s: no aggregation for cmd "
-                       "response\n", __func__);
+               mwifiex_dbg(adapter, CMD,
+                           "info: %s: no aggregation for cmd\t"
+                           "response\n", __func__);
 
                f_do_rx_cur = 1;
                goto rx_curr_single;
        }
 
        if (!card->mpa_rx.enabled) {
-               dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n",
-                       __func__);
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: rx aggregation disabled\n",
+                           __func__);
 
                f_do_rx_cur = 1;
                goto rx_curr_single;
@@ -1230,7 +1262,8 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
            (card->has_control_mask && (card->mp_rd_bitmap &
                                        (~((u32) CTRL_PORT_MASK))))) {
                /* Some more data RX pending */
-               dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: not last packet\n", __func__);
 
                if (MP_RX_AGGR_IN_PROGRESS(card)) {
                        if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) {
@@ -1247,7 +1280,8 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        } else {
                /* No more data RX pending */
-               dev_dbg(adapter->dev, "info: %s: last packet\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: last packet\n", __func__);
 
                if (MP_RX_AGGR_IN_PROGRESS(card)) {
                        f_do_rx_aggr = 1;
@@ -1262,14 +1296,16 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_aggr_cur) {
-               dev_dbg(adapter->dev, "info: current packet aggregation\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
                /* Curr pkt can be aggregated */
                mp_rx_aggr_setup(card, rx_len, port);
 
                if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) ||
                    mp_rx_aggr_port_limit_reached(card)) {
-                       dev_dbg(adapter->dev, "info: %s: aggregated packet "
-                               "limit reached\n", __func__);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: %s: aggregated packet\t"
+                                   "limit reached\n", __func__);
                        /* No more pkts allowed in Aggr buf, rx it */
                        f_do_rx_aggr = 1;
                }
@@ -1277,8 +1313,9 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        if (f_do_rx_aggr) {
                /* do aggr RX now */
-               dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n",
-                       card->mpa_rx.pkt_cnt);
+               mwifiex_dbg(adapter, DATA,
+                           "info: do_rx_aggr: num of packets: %d\n",
+                           card->mpa_rx.pkt_cnt);
 
                if (card->supports_sdio_new_mode) {
                        int i;
@@ -1318,8 +1355,9 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                                                 GFP_KERNEL |
                                                                 GFP_DMA);
                        if (!skb_deaggr) {
-                               dev_err(adapter->dev, "skb allocation failure drop pkt len=%d type=%d\n",
-                                       pkt_len, pkt_type);
+                               mwifiex_dbg(adapter, ERROR, "skb allocation failure\t"
+                                           "drop pkt len=%d type=%d\n",
+                                           pkt_len, pkt_type);
                                curr_ptr += len_arr[pind];
                                continue;
                        }
@@ -1339,12 +1377,12 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                mwifiex_decode_rx_packet(adapter, skb_deaggr,
                                                         pkt_type);
                        } else {
-                               dev_err(adapter->dev, " drop wrong aggr pkt:\t"
-                                       "sdio_single_port_rx_aggr=%d\t"
-                                       "type=%d len=%d max_len=%d\n",
-                                       adapter->sdio_rx_aggr_enable,
-                                       pkt_type, pkt_len,
-                                       len_arr[pind]);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "drop wrong aggr pkt:\t"
+                                           "sdio_single_port_rx_aggr=%d\t"
+                                           "type=%d len=%d max_len=%d\n",
+                                           adapter->sdio_rx_aggr_enable,
+                                           pkt_type, pkt_len, len_arr[pind]);
                                dev_kfree_skb_any(skb_deaggr);
                        }
                        curr_ptr += len_arr[pind];
@@ -1354,13 +1392,14 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
 rx_curr_single:
        if (f_do_rx_cur) {
-               dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n",
-                       port, rx_len);
+               mwifiex_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n",
+                           port, rx_len);
 
                skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
                if (!skb) {
-                       dev_err(adapter->dev, "single skb allocated fail,\t"
-                               "drop pkt port=%d len=%d\n", port, rx_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "single skb allocated fail,\t"
+                                   "drop pkt port=%d len=%d\n", port, rx_len);
                        if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
                                                      card->mpa_rx.buf, rx_len,
                                                      adapter->ioport + port))
@@ -1376,9 +1415,9 @@ rx_curr_single:
                        goto error;
                if (!adapter->sdio_rx_aggr_enable &&
                    pkt_type == MWIFIEX_TYPE_AGGR_DATA) {
-                       dev_err(adapter->dev, "drop wrong pkt type %d\t"
-                               "current SDIO RX Aggr not enabled\n",
-                               pkt_type);
+                       mwifiex_dbg(adapter, ERROR, "drop wrong pkt type %d\t"
+                                   "current SDIO RX Aggr not enabled\n",
+                                   pkt_type);
                        dev_kfree_skb_any(skb);
                        return 0;
                }
@@ -1386,7 +1425,8 @@ rx_curr_single:
                mwifiex_decode_rx_packet(adapter, skb, pkt_type);
        }
        if (f_post_aggr_cur) {
-               dev_dbg(adapter->dev, "info: current packet aggregation\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
                /* Curr pkt can be aggregated */
                mp_rx_aggr_setup(card, rx_len, port);
        }
@@ -1458,7 +1498,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                     MWIFIEX_RX_DATA_BUF_SIZE)
                        return -1;
                rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-               dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len);
+               mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", rx_len);
 
                skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
                if (!skb)
@@ -1469,17 +1509,17 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data,
                                              skb->len, adapter->ioport |
                                                        CMD_PORT_SLCT)) {
-                       dev_err(adapter->dev,
-                               "%s: failed to card_to_host", __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: failed to card_to_host", __func__);
                        dev_kfree_skb_any(skb);
                        goto term_cmd;
                }
 
                if ((pkt_type != MWIFIEX_TYPE_CMD) &&
                    (pkt_type != MWIFIEX_TYPE_EVENT))
-                       dev_err(adapter->dev,
-                               "%s:Received wrong packet on cmd port",
-                               __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s:Received wrong packet on cmd port",
+                                   __func__);
 
                mwifiex_decode_rx_packet(adapter, skb, pkt_type);
        }
@@ -1495,12 +1535,13 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                }
                card->mp_wr_bitmap = bitmap;
 
-               dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%x\n",
-                       card->mp_wr_bitmap);
+               mwifiex_dbg(adapter, INTR,
+                           "int: DNLD: wr_bitmap=0x%x\n",
+                           card->mp_wr_bitmap);
                if (adapter->data_sent &&
                    (card->mp_wr_bitmap & card->mp_data_port_mask)) {
-                       dev_dbg(adapter->dev,
-                               "info:  <--- Tx DONE Interrupt --->\n");
+                       mwifiex_dbg(adapter, INTR,
+                                   "info:  <--- Tx DONE Interrupt --->\n");
                        adapter->data_sent = false;
                }
        }
@@ -1517,8 +1558,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                        adapter->cmd_sent = false;
        }
 
-       dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
-               adapter->cmd_sent, adapter->data_sent);
+       mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n",
+                   adapter->cmd_sent, adapter->data_sent);
        if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
                bitmap = (u32) card->mp_regs[reg->rd_bitmap_l];
                bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8;
@@ -1529,40 +1570,45 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                                ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24;
                }
                card->mp_rd_bitmap = bitmap;
-               dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%x\n",
-                       card->mp_rd_bitmap);
+               mwifiex_dbg(adapter, INTR,
+                           "int: UPLD: rd_bitmap=0x%x\n",
+                           card->mp_rd_bitmap);
 
                while (true) {
                        ret = mwifiex_get_rd_port(adapter, &port);
                        if (ret) {
-                               dev_dbg(adapter->dev,
-                                       "info: no more rd_port available\n");
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: no more rd_port available\n");
                                break;
                        }
                        len_reg_l = reg->rd_len_p0_l + (port << 1);
                        len_reg_u = reg->rd_len_p0_u + (port << 1);
                        rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
                        rx_len |= (u16) card->mp_regs[len_reg_l];
-                       dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n",
-                               port, rx_len);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: RX: port=%d rx_len=%u\n",
+                                   port, rx_len);
                        rx_blocks =
                                (rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
                                 1) / MWIFIEX_SDIO_BLOCK_SIZE;
                        if (rx_len <= INTF_HEADER_LEN ||
                            (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
                             card->mpa_rx.buf_size) {
-                               dev_err(adapter->dev, "invalid rx_len=%d\n",
-                                       rx_len);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "invalid rx_len=%d\n",
+                                           rx_len);
                                return -1;
                        }
 
                        rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-                       dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len);
+                       mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n",
+                                   rx_len);
 
                        if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len,
                                                              port)) {
-                               dev_err(adapter->dev, "card_to_host_mpa failed:"
-                                       " int status=%#x\n", sdio_ireg);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "card_to_host_mpa failed: int status=%#x\n",
+                                           sdio_ireg);
                                goto term_cmd;
                        }
                }
@@ -1573,19 +1619,23 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 term_cmd:
        /* terminate cmd */
        if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               dev_err(adapter->dev, "read CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR, "read CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: CFG reg val = %d\n", cr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val = %d\n", cr);
 
        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04)))
-               dev_err(adapter->dev, "write CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "write CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: write success\n");
+               mwifiex_dbg(adapter, INFO, "info: write success\n");
 
        if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               dev_err(adapter->dev, "read CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "read CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: CFG reg val =%x\n", cr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val =%x\n", cr);
 
        return -1;
 }
@@ -1619,8 +1669,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        if (!card->mpa_tx.enabled ||
            (card->has_control_mask && (port == CTRL_PORT)) ||
            (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) {
-               dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n",
-                       __func__);
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: tx aggregation disabled\n",
+                           __func__);
 
                f_send_cur_buf = 1;
                goto tx_curr_single;
@@ -1628,8 +1679,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
 
        if (next_pkt_len) {
                /* More pkt in TX queue */
-               dev_dbg(adapter->dev, "info: %s: more packets in queue.\n",
-                       __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: more packets in queue.\n",
+                           __func__);
 
                if (MP_TX_AGGR_IN_PROGRESS(card)) {
                        if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
@@ -1659,8 +1711,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
                }
        } else {
                /* Last pkt in TX queue */
-               dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n",
-                       __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: Last packet in Tx Queue.\n",
+                           __func__);
 
                if (MP_TX_AGGR_IN_PROGRESS(card)) {
                        /* some packs in Aggr buf already */
@@ -1677,8 +1730,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_precopy_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: precopy current buffer\n",
-                       __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: precopy current buffer\n",
+                           __func__);
                MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
 
                if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
@@ -1688,9 +1742,10 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_send_aggr_buf) {
-               dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n",
-                       __func__,
-                               card->mpa_tx.start_port, card->mpa_tx.ports);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send aggr buffer: %d %d\n",
+                           __func__, card->mpa_tx.start_port,
+                           card->mpa_tx.ports);
                if (card->supports_sdio_new_mode) {
                        u32 port_count;
                        int i;
@@ -1719,15 +1774,17 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
 
 tx_curr_single:
        if (f_send_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: send current buffer %d\n",
-                       __func__, port);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send current buffer %d\n",
+                           __func__, port);
                ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
                                                 adapter->ioport + port);
        }
 
        if (f_postcopy_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n",
-                       __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: postcopy current buffer\n",
+                           __func__);
                MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
        }
 
@@ -1771,8 +1828,9 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
        if (type == MWIFIEX_TYPE_DATA) {
                ret = mwifiex_get_wr_port_data(adapter, &port);
                if (ret) {
-                       dev_err(adapter->dev, "%s: no wr_port available\n",
-                               __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: no wr_port available\n",
+                                   __func__);
                        return ret;
                }
        } else {
@@ -1781,8 +1839,9 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
 
                if (pkt_len <= INTF_HEADER_LEN ||
                    pkt_len > MWIFIEX_UPLD_SIZE)
-                       dev_err(adapter->dev, "%s: payload=%p, nb=%d\n",
-                               __func__, payload, pkt_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: payload=%p, nb=%d\n",
+                                   __func__, payload, pkt_len);
 
                if (card->supports_sdio_new_mode)
                        port = CMD_PORT_SLCT;
@@ -1896,7 +1955,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
        sdio_release_host(func);
        if (ret) {
-               pr_err("cannot set SDIO block size\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot set SDIO block size\n");
                return ret;
        }
 
@@ -1977,7 +2037,8 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
                                             card->mp_tx_agg_buf_size,
                                             card->mp_rx_agg_buf_size);
        if (ret) {
-               dev_err(adapter->dev, "failed to alloc sdio mp-a buffers\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "failed to alloc sdio mp-a buffers\n");
                kfree(card->mp_regs);
                return -1;
        }
@@ -2041,8 +2102,9 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
 
        card->curr_wr_port = reg->start_wr_port;
 
-       dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n",
-               port, card->mp_data_port_mask);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: mp_end_port %d, data port mask 0x%x\n",
+                   port, card->mp_data_port_mask);
 }
 
 static struct mwifiex_adapter *save_adapter;
@@ -2059,7 +2121,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
         * We run it in a totally independent workqueue.
         */
 
-       pr_err("Resetting card...\n");
+       mwifiex_dbg(adapter, WARN, "Resetting card...\n");
        mmc_remove_host(target);
        /* 200ms delay is based on experiment with sdhci controller */
        mdelay(200);
@@ -2079,14 +2141,14 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
        sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
                    &ret);
        if (ret) {
-               dev_err(adapter->dev, "SDIO Write ERR\n");
+               mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n");
                return RDWR_STATUS_FAILURE;
        }
        for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
                ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
                                       &ret);
                if (ret) {
-                       dev_err(adapter->dev, "SDIO read err\n");
+                       mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
                        return RDWR_STATUS_FAILURE;
                }
                if (ctrl_data == FW_DUMP_DONE)
@@ -2094,19 +2156,20 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
                if (doneflag && ctrl_data == doneflag)
                        return RDWR_STATUS_DONE;
                if (ctrl_data != FW_DUMP_HOST_READY) {
-                       dev_info(adapter->dev,
-                                "The ctrl reg was changed, re-try again!\n");
+                       mwifiex_dbg(adapter, WARN,
+                                   "The ctrl reg was changed, re-try again!\n");
                        sdio_writeb(card->func, FW_DUMP_HOST_READY,
                                    card->reg->fw_dump_ctrl, &ret);
                        if (ret) {
-                               dev_err(adapter->dev, "SDIO write err\n");
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
                                return RDWR_STATUS_FAILURE;
                        }
                }
                usleep_range(100, 200);
        }
        if (ctrl_data == FW_DUMP_HOST_READY) {
-               dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "Fail to pull ctrl_data\n");
                return RDWR_STATUS_FAILURE;
        }
 
@@ -2114,7 +2177,7 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
 }
 
 /* This function dump firmware memory to file */
-static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
+static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
 {
        struct sdio_mmc_card *card = adapter->card;
        int ret = 0;
@@ -2122,9 +2185,6 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
        enum rdwr_status stat;
        u32 memory_size;
-       static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };
-
-       mwifiex_dump_drv_info(adapter);
 
        if (!card->can_dump_fw)
                return;
@@ -2142,7 +2202,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        mwifiex_pm_wakeup_card(adapter);
        sdio_claim_host(card->func);
 
-       dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
 
        stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
        if (stat == RDWR_STATUS_FAILURE)
@@ -2152,7 +2212,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        /* Read the number of the memories which will dump */
        dump_num = sdio_readb(card->func, reg, &ret);
        if (ret) {
-               dev_err(adapter->dev, "SDIO read memory length err\n");
+               mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n");
                goto done;
        }
 
@@ -2169,7 +2229,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                for (i = 0; i < 4; i++) {
                        read_reg = sdio_readb(card->func, reg, &ret);
                        if (ret) {
-                               dev_err(adapter->dev, "SDIO read err\n");
+                               mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
                                goto done;
                        }
                        memory_size |= (read_reg << i*8);
@@ -2177,25 +2237,33 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                }
 
                if (memory_size == 0) {
-                       dev_info(adapter->dev, "Firmware dump Finished!\n");
+                       mwifiex_dbg(adapter, DUMP, "Firmware dump Finished!\n");
+                       ret = mwifiex_write_reg(adapter,
+                                               card->reg->fw_dump_ctrl,
+                                               FW_DUMP_READ_DONE);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
+                               return;
+                       }
                        break;
                }
 
-               dev_info(adapter->dev,
-                        "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+               mwifiex_dbg(adapter, DUMP,
+                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
                entry->mem_ptr = vmalloc(memory_size + 1);
                entry->mem_size = memory_size;
                if (!entry->mem_ptr) {
-                       dev_err(adapter->dev, "Vmalloc %s failed\n",
-                               entry->mem_name);
+                       mwifiex_dbg(adapter, ERROR, "Vmalloc %s failed\n",
+                                   entry->mem_name);
                        goto done;
                }
                dbg_ptr = entry->mem_ptr;
                end_ptr = dbg_ptr + memory_size;
 
                doneflag = entry->done_flag;
-               dev_info(adapter->dev, "Start %s output, please wait...\n",
-                        entry->mem_name);
+               mwifiex_dbg(adapter, DUMP,
+                           "Start %s output, please wait...\n",
+                           entry->mem_name);
 
                do {
                        stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
@@ -2207,39 +2275,43 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                        for (reg = reg_start; reg <= reg_end; reg++) {
                                *dbg_ptr = sdio_readb(card->func, reg, &ret);
                                if (ret) {
-                                       dev_err(adapter->dev,
-                                               "SDIO read err\n");
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "SDIO read err\n");
                                        goto done;
                                }
                                if (dbg_ptr < end_ptr)
                                        dbg_ptr++;
                                else
-                                       dev_err(adapter->dev,
-                                               "Allocated buf not enough\n");
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Allocated buf not enough\n");
                        }
 
                        if (stat != RDWR_STATUS_DONE)
                                continue;
 
-                       dev_info(adapter->dev, "%s done: size=0x%tx\n",
-                                entry->mem_name, dbg_ptr - entry->mem_ptr);
+                       mwifiex_dbg(adapter, DUMP, "%s done: size=0x%tx\n",
+                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
                        break;
                } while (1);
        }
-       dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
-
-       kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
 
 done:
        sdio_release_host(card->func);
-       adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
+{
+       mwifiex_drv_info_dump(adapter);
+       mwifiex_sdio_fw_dump(adapter);
+       mwifiex_upload_device_dump(adapter);
 }
 
 static void mwifiex_sdio_work(struct work_struct *work)
 {
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
                               &iface_work_flags))
-               mwifiex_sdio_fw_dump_work(save_adapter);
+               mwifiex_sdio_device_dump_work(save_adapter);
        if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
                               &iface_work_flags))
                mwifiex_sdio_card_reset_work(save_adapter);
@@ -2259,13 +2331,13 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
 }
 
 /* This function dumps FW information */
-static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
+static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
 {
        save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags))
+       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
                return;
 
-       set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags);
+       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
        schedule_work(&sdio_work);
 }
 
@@ -2285,7 +2357,7 @@ mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
        if (!p)
                return 0;
 
-       dev_info(adapter->dev, "SDIO register DUMP START\n");
+       mwifiex_dbg(adapter, MSG, "SDIO register dump start\n");
 
        mwifiex_pm_wakeup_card(adapter);
 
@@ -2351,13 +2423,13 @@ mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
                                reg++;
                }
 
-               dev_info(adapter->dev, "%s\n", buf);
+               mwifiex_dbg(adapter, MSG, "%s\n", buf);
                p += sprintf(p, "%s\n", buf);
        }
 
        sdio_release_host(cardp->func);
 
-       dev_info(adapter->dev, "SDIO register DUMP END\n");
+       mwifiex_dbg(adapter, MSG, "SDIO register dump end\n");
 
        return p - drv_buf;
 }
@@ -2382,8 +2454,8 @@ static struct mwifiex_if_ops sdio_ops = {
        .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
        .event_complete = mwifiex_sdio_event_complete,
        .card_reset = mwifiex_sdio_card_reset,
-       .fw_dump = mwifiex_sdio_fw_dump,
        .reg_dump = mwifiex_sdio_reg_dump,
+       .device_dump = mwifiex_sdio_device_dump,
        .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
 };
 
index 49422f2a53809fe0c241de93afb231c8011871c3..037adcd1f484abeb5f54478893ab7b1ff2b7ab76 100644 (file)
@@ -77,8 +77,8 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
        struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
 
        if (cmd_action != HostCmd_ACT_GEN_SET) {
-               dev_err(priv->adapter->dev,
-                       "mac_control: only support set cmd\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "mac_control: only support set cmd\n");
                return -1;
        }
 
@@ -112,7 +112,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 {
        struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
 
-       dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
                                - 1 + S_DS_GEN);
@@ -129,11 +130,11 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                le16_add_cpu(&cmd->size, sizeof(u16));
        }
 
-       dev_dbg(priv->adapter->dev,
-               "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x,"
-               " Value=0x%x\n",
-               cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
-               le16_to_cpu(*(__le16 *) snmp_mib->value));
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
+                   "OIDSize=0x%x, Value=0x%x\n",
+                   cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
+                   le16_to_cpu(*(__le16 *)snmp_mib->value));
        return 0;
 }
 
@@ -356,9 +357,9 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
            (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) &&
            ((adapter->arp_filter_size > 0) &&
             (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
-               dev_dbg(adapter->dev,
-                       "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
-                       adapter->arp_filter_size);
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
+                           adapter->arp_filter_size);
                memcpy(((u8 *) hs_cfg) +
                       sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
                       adapter->arp_filter, adapter->arp_filter_size);
@@ -378,11 +379,11 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
                hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
                hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
                hs_cfg->params.hs_config.gap = hscfg_param->gap;
-               dev_dbg(adapter->dev,
-                       "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
-                      hs_cfg->params.hs_config.conditions,
-                      hs_cfg->params.hs_config.gpio,
-                      hs_cfg->params.hs_config.gap);
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
+                           hs_cfg->params.hs_config.conditions,
+                           hs_cfg->params.hs_config.gpio,
+                           hs_cfg->params.hs_config.gap);
        }
 
        return 0;
@@ -462,7 +463,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
        /* Set AP MAC address */
        memcpy(deauth->mac_addr, mac, ETH_ALEN);
 
-       dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
+       mwifiex_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr);
 
        deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
 
@@ -540,9 +541,9 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
                } else if (!priv->wep_key[i].key_length) {
                        continue;
                } else {
-                       dev_err(priv->adapter->dev,
-                               "key%d Length = %d is incorrect\n",
-                              (i + 1), priv->wep_key[i].key_length);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "key%d Length = %d is incorrect\n",
+                                   (i + 1), priv->wep_key[i].key_length);
                        return -1;
                }
        }
@@ -562,7 +563,8 @@ static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv,
        u16 size, len = KEY_PARAMS_FIXED_LEN;
 
        if (enc_key->is_igtk_key) {
-               dev_dbg(adapter->dev, "%s: Set CMAC AES Key\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set CMAC AES Key\n", __func__);
                if (enc_key->is_rx_seq_valid)
                        memcpy(km->key_param_set.key_params.cmac_aes.ipn,
                               enc_key->pn, enc_key->pn_len);
@@ -575,7 +577,8 @@ static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv,
                       enc_key->key_material, enc_key->key_len);
                len += sizeof(struct mwifiex_cmac_aes_param);
        } else {
-               dev_dbg(adapter->dev, "%s: Set AES Key\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set AES Key\n", __func__);
                if (enc_key->is_rx_seq_valid)
                        memcpy(km->key_param_set.key_params.aes.pn,
                               enc_key->pn, enc_key->pn_len);
@@ -619,7 +622,7 @@ mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
        km->action = cpu_to_le16(cmd_action);
 
        if (cmd_action == HostCmd_ACT_GEN_GET) {
-               dev_dbg(adapter->dev, "%s: Get key\n", __func__);
+               mwifiex_dbg(adapter, INFO, "%s: Get key\n", __func__);
                km->key_param_set.key_idx =
                                        enc_key->key_index & KEY_INDEX_MASK;
                km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
@@ -646,7 +649,7 @@ mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
               sizeof(struct mwifiex_ie_type_key_param_set_v2));
 
        if (enc_key->key_disable) {
-               dev_dbg(adapter->dev, "%s: Remove key\n", __func__);
+               mwifiex_dbg(adapter, INFO, "%s: Remove key\n", __func__);
                km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
                km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
                km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
@@ -667,7 +670,7 @@ mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
        memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN);
 
        if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
-               dev_dbg(adapter->dev, "%s: Set WEP Key\n", __func__);
+               mwifiex_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__);
                len += sizeof(struct mwifiex_wep_param);
                km->key_param_set.len = cpu_to_le16(len);
                km->key_param_set.key_type = KEY_TYPE_ID_WEP;
@@ -710,7 +713,7 @@ mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
                key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
 
        if (enc_key->is_wapi_key) {
-               dev_dbg(adapter->dev, "%s: Set WAPI Key\n", __func__);
+               mwifiex_dbg(adapter, INFO, "%s: Set WAPI Key\n", __func__);
                km->key_param_set.key_type = KEY_TYPE_ID_WAPI;
                memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn,
                       PN_LEN);
@@ -750,7 +753,8 @@ mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv,
                return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km);
 
        if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
-               dev_dbg(adapter->dev, "%s: Set TKIP Key\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "%s: Set TKIP Key\n", __func__);
                if (enc_key->is_rx_seq_valid)
                        memcpy(km->key_param_set.key_params.tkip.pn,
                               enc_key->pn, enc_key->pn_len);
@@ -814,7 +818,7 @@ mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
                memset(&key_material->key_param_set, 0,
                       sizeof(struct mwifiex_ie_type_key_param_set));
        if (enc_key->is_wapi_key) {
-               dev_dbg(priv->adapter->dev, "info: Set WAPI Key\n");
+               mwifiex_dbg(priv->adapter, INFO, "info: Set WAPI Key\n");
                key_material->key_param_set.key_type_id =
                                                cpu_to_le16(KEY_TYPE_ID_WAPI);
                if (cmd_oid == KEY_INFO_ENABLED)
@@ -860,7 +864,7 @@ mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
        }
        if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
                if (enc_key->is_igtk_key) {
-                       dev_dbg(priv->adapter->dev, "cmd: CMAC_AES\n");
+                       mwifiex_dbg(priv->adapter, CMD, "cmd: CMAC_AES\n");
                        key_material->key_param_set.key_type_id =
                                        cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
                        if (cmd_oid == KEY_INFO_ENABLED)
@@ -873,7 +877,7 @@ mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
                        key_material->key_param_set.key_info |=
                                                        cpu_to_le16(KEY_IGTK);
                } else {
-                       dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
+                       mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_AES\n");
                        key_material->key_param_set.key_type_id =
                                                cpu_to_le16(KEY_TYPE_ID_AES);
                        if (cmd_oid == KEY_INFO_ENABLED)
@@ -892,7 +896,7 @@ mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv,
                                                        cpu_to_le16(KEY_MCAST);
                }
        } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
-               dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
+               mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_TKIP\n");
                key_material->key_param_set.key_type_id =
                                                cpu_to_le16(KEY_TYPE_ID_TKIP);
                key_material->key_param_set.key_info =
@@ -999,7 +1003,8 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
                &domain_info->domain;
        u8 no_of_triplet = adapter->domain_reg.no_of_triplet;
 
-       dev_dbg(adapter->dev, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
+       mwifiex_dbg(adapter, INFO,
+                   "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
 
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
        domain_info->action = cpu_to_le16(cmd_action);
@@ -1071,6 +1076,26 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
        return 0;
 }
 
+/* This function prepares command buffer to get/set memory location value.
+ */
+static int
+mwifiex_cmd_mem_access(struct host_cmd_ds_command *cmd, u16 cmd_action,
+                      void *pdata_buf)
+{
+       struct mwifiex_ds_mem_rw *mem_rw = (void *)pdata_buf;
+       struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) +
+                               S_DS_GEN);
+
+       mem_access->action = cpu_to_le16(cmd_action);
+       mem_access->addr = cpu_to_le32(mem_rw->addr);
+       mem_access->value = cpu_to_le32(mem_rw->value);
+
+       return 0;
+}
+
 /*
  * This function prepares command to set/get register value.
  *
@@ -1215,8 +1240,9 @@ mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
                                                (u32)(card->sleep_cookie_pbase);
                host_spec->sleep_cookie_addr_hi =
                                 (u32)(((u64)(card->sleep_cookie_pbase)) >> 32);
-               dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: 0x%x\n",
-                       host_spec->sleep_cookie_addr_lo);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "sleep_cook_lo phy addr: 0x%x\n",
+                           host_spec->sleep_cookie_addr_lo);
        }
 
        return 0;
@@ -1243,7 +1269,8 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
                                S_DS_GEN);
 
        subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action);
-       dev_dbg(priv->adapter->dev, "cmd: action: %d\n", subsc_evt_cfg->action);
+       mwifiex_dbg(priv->adapter, CMD,
+                   "cmd: action: %d\n", subsc_evt_cfg->action);
 
        /*For query requests, no configuration TLV structures are to be added.*/
        if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET)
@@ -1252,14 +1279,15 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
        subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events);
 
        event_bitmap = subsc_evt_cfg->events;
-       dev_dbg(priv->adapter->dev, "cmd: event bitmap : %16x\n",
-               event_bitmap);
+       mwifiex_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n",
+                   event_bitmap);
 
        if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) ||
             (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) &&
            (event_bitmap == 0)) {
-               dev_dbg(priv->adapter->dev, "Error: No event specified "
-                       "for bitwise action type\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Error: No event specified\t"
+                           "for bitwise action type\n");
                return -EINVAL;
        }
 
@@ -1284,10 +1312,11 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
                rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value;
                rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq;
 
-               dev_dbg(priv->adapter->dev, "Cfg Beacon Low Rssi event, "
-                       "RSSI:-%d dBm, Freq:%d\n",
-                       subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
-                       subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "Cfg Beacon Low Rssi event,\t"
+                           "RSSI:-%d dBm, Freq:%d\n",
+                           subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
+                           subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
 
                pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
                le16_add_cpu(&cmd->size,
@@ -1304,10 +1333,11 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
                rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value;
                rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq;
 
-               dev_dbg(priv->adapter->dev, "Cfg Beacon High Rssi event, "
-                       "RSSI:-%d dBm, Freq:%d\n",
-                       subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
-                       subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "Cfg Beacon High Rssi event,\t"
+                           "RSSI:-%d dBm, Freq:%d\n",
+                           subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
+                           subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
 
                pos += sizeof(struct mwifiex_ie_types_rssi_threshold);
                le16_add_cpu(&cmd->size,
@@ -1463,12 +1493,14 @@ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
                                                data, len);
                if (ret)
                        return ret;
-               dev_dbg(adapter->dev,
-                       "download cfg_data from device tree: %s\n", prop->name);
+               mwifiex_dbg(adapter, INFO,
+                           "download cfg_data from device tree: %s\n",
+                           prop->name);
        } else if (adapter->cal_data->data && adapter->cal_data->size > 0) {
                len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
                                            adapter->cal_data->size, data);
-               dev_dbg(adapter->dev, "download cfg_data from config file\n");
+               mwifiex_dbg(adapter, INFO,
+                           "download cfg_data from config file\n");
        } else {
                return -1;
        }
@@ -1583,9 +1615,9 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
                tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG);
 
                if (!params) {
-                       dev_err(priv->adapter->dev,
-                               "TDLS config params not available for %pM\n",
-                               oper->peer_mac);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS config params not available for %pM\n",
+                                   oper->peer_mac);
                        return -ENODATA;
                }
 
@@ -1663,7 +1695,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
 
                break;
        default:
-               dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS operation\n");
                return -ENOTSUPP;
        }
 
@@ -1870,8 +1902,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf);
                break;
        case HostCmd_CMD_WMM_GET_STATUS:
-               dev_dbg(priv->adapter->dev,
-                       "cmd: WMM: WMM_GET_STATUS cmd sent\n");
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: WMM: WMM_GET_STATUS cmd sent\n");
                cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
                cmd_ptr->size =
                        cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) +
@@ -1885,6 +1917,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
        case HostCmd_CMD_802_11_SCAN_EXT:
                ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf);
                break;
+       case HostCmd_CMD_MEM_ACCESS:
+               ret = mwifiex_cmd_mem_access(cmd_ptr, cmd_action, data_buf);
+               break;
        case HostCmd_CMD_MAC_REG_ACCESS:
        case HostCmd_CMD_BBP_REG_ACCESS:
        case HostCmd_CMD_RF_REG_ACCESS:
@@ -1932,8 +1967,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                                   data_buf);
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "PREP_CMD: unknown cmd- %#x\n", cmd_no);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "PREP_CMD: unknown cmd- %#x\n", cmd_no);
                ret = -1;
                break;
        }
@@ -2024,8 +2059,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
                                               &sdio_sp_rx_aggr_enable,
                                               true);
                        if (ret) {
-                               dev_err(priv->adapter->dev,
-                                       "error while enabling SP aggregation..disable it");
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "error while enabling SP aggregation..disable it");
                                adapter->sdio_rx_aggr_enable = false;
                        }
                }
@@ -2108,8 +2143,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
                                       HostCmd_ACT_GEN_SET, DOT11D_I,
                                       &state_11d, true);
                if (ret)
-                       dev_err(priv->adapter->dev,
-                               "11D: failed to enable 11D\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "11D: failed to enable 11D\n");
        }
 
        /* Send cmd to FW to configure 11n specific configuration
index 88dc6b672ef43adb5cc8c1b836b19a1bed0db5d1..aa5b9a310340df972dd5142ede815366d25a0d5b 100644 (file)
@@ -49,8 +49,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
        struct host_cmd_ds_802_11_ps_mode_enh *pm;
        unsigned long flags;
 
-       dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
-               resp->command, resp->result);
+       mwifiex_dbg(adapter, ERROR,
+                   "CMD_RESP: cmd %#x error, result=%#x\n",
+                   resp->command, resp->result);
 
        if (adapter->curr_cmd->wait_q_enabled)
                adapter->cmd_wait_q.status = -1;
@@ -58,9 +59,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
        switch (le16_to_cpu(resp->command)) {
        case HostCmd_CMD_802_11_PS_MODE_ENH:
                pm = &resp->params.psmode_enh;
-               dev_err(adapter->dev,
-                       "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
-                       resp->result, le16_to_cpu(pm->action));
+               mwifiex_dbg(adapter, ERROR,
+                           "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
+                           resp->result, le16_to_cpu(pm->action));
                /* We do not re-try enter-ps command in ad-hoc mode. */
                if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
                    (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
@@ -91,7 +92,8 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
                break;
 
        case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
-               dev_err(priv->adapter->dev, "SDIO RX single-port aggregation Not support\n");
+               mwifiex_dbg(adapter, MSG,
+                           "SDIO RX single-port aggregation Not support\n");
                break;
 
        default:
@@ -187,29 +189,34 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
        u16 query_type = le16_to_cpu(smib->query_type);
        u32 ul_temp;
 
-       dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x,"
-               " query_type = %#x, buf size = %#x\n",
-               oid, query_type, le16_to_cpu(smib->buf_size));
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: SNMP_RESP: oid value = %#x,\t"
+                   "query_type = %#x, buf size = %#x\n",
+                   oid, query_type, le16_to_cpu(smib->buf_size));
        if (query_type == HostCmd_ACT_GEN_GET) {
                ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
                if (data_buf)
                        *data_buf = ul_temp;
                switch (oid) {
                case FRAG_THRESH_I:
-                       dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: FragThsd =%u\n", ul_temp);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: FragThsd =%u\n",
+                                   ul_temp);
                        break;
                case RTS_THRESH_I:
-                       dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: RTSThsd =%u\n", ul_temp);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: RTSThsd =%u\n",
+                                   ul_temp);
                        break;
                case SHORT_RETRY_LIM_I:
-                       dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: TxRetryCount=%u\n",
+                                   ul_temp);
                        break;
                case DTIM_PERIOD_I:
-                       dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: DTIM period=%u\n", ul_temp);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: SNMP_RESP: DTIM period=%u\n",
+                                   ul_temp);
                default:
                        break;
                }
@@ -426,14 +433,15 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
                        priv->tx_power_level = (u16) pg->power_min;
                break;
        default:
-               dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n",
-                       action);
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: unknown cmd action %d\n",
+                           action);
                return 0;
        }
-       dev_dbg(adapter->dev,
-               "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
-              priv->tx_power_level, priv->max_tx_power_level,
-              priv->min_tx_power_level);
+       mwifiex_dbg(adapter, INFO,
+                   "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
+                   priv->tx_power_level, priv->max_tx_power_level,
+                   priv->min_tx_power_level);
 
        return 0;
 }
@@ -454,10 +462,10 @@ static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
                priv->min_tx_power_level = txp->min_power;
        }
 
-       dev_dbg(priv->adapter->dev,
-               "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
-               priv->tx_power_level, priv->max_tx_power_level,
-               priv->min_tx_power_level);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
+                   priv->tx_power_level, priv->max_tx_power_level,
+                   priv->min_tx_power_level);
 
        return 0;
 }
@@ -473,18 +481,18 @@ static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
        struct mwifiex_adapter *adapter = priv->adapter;
 
        if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-               dev_dbg(adapter->dev,
-                       "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
-                       Rx action = 0x%x, Rx Mode = 0x%04x\n",
-                       le16_to_cpu(ant_mimo->action_tx),
-                       le16_to_cpu(ant_mimo->tx_ant_mode),
-                       le16_to_cpu(ant_mimo->action_rx),
-                       le16_to_cpu(ant_mimo->rx_ant_mode));
+               mwifiex_dbg(adapter, INFO,
+                           "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
+                           "Rx action = 0x%x, Rx Mode = 0x%04x\n",
+                           le16_to_cpu(ant_mimo->action_tx),
+                           le16_to_cpu(ant_mimo->tx_ant_mode),
+                           le16_to_cpu(ant_mimo->action_rx),
+                           le16_to_cpu(ant_mimo->rx_ant_mode));
        else
-               dev_dbg(adapter->dev,
-                       "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
-                       le16_to_cpu(ant_siso->action),
-                       le16_to_cpu(ant_siso->ant_mode));
+               mwifiex_dbg(adapter, INFO,
+                           "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
+                           le16_to_cpu(ant_siso->action),
+                           le16_to_cpu(ant_siso->ant_mode));
 
        return 0;
 }
@@ -502,8 +510,8 @@ static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
 
        memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
 
-       dev_dbg(priv->adapter->dev,
-               "info: set mac address: %pM\n", priv->curr_addr);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: set mac address: %pM\n", priv->curr_addr);
 
        return 0;
 }
@@ -587,7 +595,8 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
 
        if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
                if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
-                       dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: key: GTK is set\n");
                        priv->wpa_is_gtk_set = true;
                        priv->scan_block = false;
                }
@@ -617,7 +626,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
        key_v2 = &resp->params.key_material_v2;
        if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
                if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
-                       dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
+                       mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
                        priv->wpa_is_gtk_set = true;
                        priv->scan_block = false;
                }
@@ -663,14 +672,14 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
                                - IEEE80211_COUNTRY_STRING_LEN)
                              / sizeof(struct ieee80211_country_ie_triplet));
 
-       dev_dbg(priv->adapter->dev,
-               "info: 11D Domain Info Resp: no_of_triplet=%d\n",
-               no_of_triplet);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: 11D Domain Info Resp: no_of_triplet=%d\n",
+                   no_of_triplet);
 
        if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
-               dev_warn(priv->adapter->dev,
-                        "11D: invalid number of triplets %d returned\n",
-                        no_of_triplet);
+               mwifiex_dbg(priv->adapter, FATAL,
+                           "11D: invalid number of triplets %d returned\n",
+                           no_of_triplet);
                return -1;
        }
 
@@ -680,8 +689,8 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
        case HostCmd_ACT_GEN_GET:
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "11D: invalid action:%d\n", domain_info->action);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: invalid action:%d\n", domain_info->action);
                return -1;
        }
 
@@ -741,6 +750,19 @@ mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
        return 0;
 }
 
+/* This function handles the command response of mem_access command
+ */
+static int
+mwifiex_ret_mem_access(struct mwifiex_private *priv,
+                      struct host_cmd_ds_command *resp, void *pioctl_buf)
+{
+       struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
+
+       priv->mem_rw.addr = le32_to_cpu(mem->addr);
+       priv->mem_rw.value = le32_to_cpu(mem->value);
+
+       return 0;
+}
 /*
  * This function handles the command response of register access.
  *
@@ -830,12 +852,12 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
        if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
                return 0;
 
-       dev_dbg(priv->adapter->dev,
-               "info: new BSSID %pM\n", ibss_coal_resp->bssid);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: new BSSID %pM\n", ibss_coal_resp->bssid);
 
        /* If rsp has NULL BSSID, Just return..... No Action */
        if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
-               dev_warn(priv->adapter->dev, "new BSSID is NULL\n");
+               mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n");
                return 0;
        }
 
@@ -871,48 +893,48 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
        case ACT_TDLS_DELETE:
                if (reason) {
                        if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
-                               dev_dbg(priv->adapter->dev,
-                                       "TDLS link delete for %pM failed: reason %d\n",
-                                       cmd_tdls_oper->peer_mac, reason);
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "TDLS link delete for %pM failed: reason %d\n",
+                                           cmd_tdls_oper->peer_mac, reason);
                        else
-                               dev_err(priv->adapter->dev,
-                                       "TDLS link delete for %pM failed: reason %d\n",
-                                       cmd_tdls_oper->peer_mac, reason);
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "TDLS link delete for %pM failed: reason %d\n",
+                                           cmd_tdls_oper->peer_mac, reason);
                } else {
-                       dev_dbg(priv->adapter->dev,
-                               "TDLS link delete for %pM successful\n",
-                               cmd_tdls_oper->peer_mac);
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link delete for %pM successful\n",
+                                   cmd_tdls_oper->peer_mac);
                }
                break;
        case ACT_TDLS_CREATE:
                if (reason) {
-                       dev_err(priv->adapter->dev,
-                               "TDLS link creation for %pM failed: reason %d",
-                               cmd_tdls_oper->peer_mac, reason);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS link creation for %pM failed: reason %d",
+                                   cmd_tdls_oper->peer_mac, reason);
                        if (node && reason != TDLS_ERR_LINK_EXISTS)
                                node->tdls_status = TDLS_SETUP_FAILURE;
                } else {
-                       dev_dbg(priv->adapter->dev,
-                               "TDLS link creation for %pM successful",
-                               cmd_tdls_oper->peer_mac);
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link creation for %pM successful",
+                                   cmd_tdls_oper->peer_mac);
                }
                break;
        case ACT_TDLS_CONFIG:
                if (reason) {
-                       dev_err(priv->adapter->dev,
-                               "TDLS link config for %pM failed, reason %d\n",
-                               cmd_tdls_oper->peer_mac, reason);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "TDLS link config for %pM failed, reason %d\n",
+                                   cmd_tdls_oper->peer_mac, reason);
                        if (node)
                                node->tdls_status = TDLS_SETUP_FAILURE;
                } else {
-                       dev_dbg(priv->adapter->dev,
-                               "TDLS link config for %pM successful\n",
-                               cmd_tdls_oper->peer_mac);
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "TDLS link config for %pM successful\n",
+                                   cmd_tdls_oper->peer_mac);
                }
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "Unknown TDLS command action response %d", action);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS command action response %d", action);
                return -1;
        }
 
@@ -929,8 +951,9 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
 
        /* For every subscribe event command (Get/Set/Clear), FW reports the
         * current set of subscribed events*/
-       dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n",
-               le16_to_cpu(cmd_sub_event->events));
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "Bitmap of currently subscribed events: %16x\n",
+                   le16_to_cpu(cmd_sub_event->events));
 
        return 0;
 }
@@ -940,7 +963,7 @@ static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
                                struct host_cmd_ds_command *resp)
 {
        if (resp->result != HostCmd_RESULT_OK) {
-               dev_err(priv->adapter->dev, "Cal data cmd resp failed\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
                return -1;
        }
 
@@ -1008,8 +1031,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                break;
        case HostCmd_CMD_802_11_BG_SCAN_QUERY:
                ret = mwifiex_ret_802_11_scan(priv, resp);
-               dev_dbg(adapter->dev,
-                       "info: CMD_RESP: BG_SCAN result is ready!\n");
+               mwifiex_dbg(adapter, CMD,
+                           "info: CMD_RESP: BG_SCAN result is ready!\n");
                break;
        case HostCmd_CMD_TXPWR_CFG:
                ret = mwifiex_ret_tx_power_cfg(priv, resp);
@@ -1088,8 +1111,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                                        / MWIFIEX_SDIO_BLOCK_SIZE)
                                       * MWIFIEX_SDIO_BLOCK_SIZE;
                adapter->curr_tx_buf_size = adapter->tx_buf_size;
-               dev_dbg(adapter->dev, "cmd: curr_tx_buf_size=%d\n",
-                       adapter->curr_tx_buf_size);
+               mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
+                           adapter->curr_tx_buf_size);
 
                if (adapter->if_ops.update_mp_end_port)
                        adapter->if_ops.update_mp_end_port(adapter,
@@ -1103,6 +1126,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
        case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
                ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
                break;
+       case HostCmd_CMD_MEM_ACCESS:
+               ret = mwifiex_ret_mem_access(priv, resp, data_buf);
+               break;
        case HostCmd_CMD_MAC_REG_ACCESS:
        case HostCmd_CMD_BBP_REG_ACCESS:
        case HostCmd_CMD_RF_REG_ACCESS:
@@ -1146,8 +1172,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
                break;
        default:
-               dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
-                       resp->command);
+               mwifiex_dbg(adapter, ERROR,
+                           "CMD_RESP: unknown cmd response %#x\n",
+                           resp->command);
                break;
        }
 
index c9064b88d6a4d6bbe33da26d09c4e296e14c7ed0..95203780010ae5a0887120c85969f9fdac22a1d6 100644 (file)
@@ -48,7 +48,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
        if (!priv->media_connected)
                return;
 
-       dev_dbg(adapter->dev, "info: handles disconnect event\n");
+       mwifiex_dbg(adapter, INFO,
+                   "info: handles disconnect event\n");
 
        priv->media_connected = false;
 
@@ -104,12 +105,14 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
         * it could be used for re-assoc
         */
 
-       dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n",
-               priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
+       mwifiex_dbg(adapter, INFO,
+                   "info: previous SSID=%s, SSID len=%u\n",
+                   priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
 
-       dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n",
-               priv->curr_bss_params.bss_descriptor.ssid.ssid,
-               priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+       mwifiex_dbg(adapter, INFO,
+                   "info: current SSID=%s, SSID len=%u\n",
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid,
+                   priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
 
        memcpy(&priv->prev_ssid,
               &priv->curr_bss_params.bss_descriptor.ssid,
@@ -127,9 +130,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
        if (adapter->is_cmd_timedout && adapter->curr_cmd)
                return;
        priv->media_connected = false;
-       dev_dbg(adapter->dev,
-               "info: successfully disconnected from %pM: reason code %d\n",
-               priv->cfg_bssid, reason_code);
+       mwifiex_dbg(adapter, MSG,
+                   "info: successfully disconnected from %pM: reason code %d\n",
+                   priv->cfg_bssid, reason_code);
        if (priv->bss_mode == NL80211_IFTYPE_STATION ||
            priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
                cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
@@ -154,13 +157,13 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
        /* reserved 2 bytes are not mandatory in tdls event */
        if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
                              sizeof(u16) - sizeof(adapter->event_cause))) {
-               dev_err(adapter->dev, "Invalid event length!\n");
+               mwifiex_dbg(adapter, ERROR, "Invalid event length!\n");
                return -1;
        }
 
        sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
        if (!sta_ptr) {
-               dev_err(adapter->dev, "cannot get sta entry!\n");
+               mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n");
                return -1;
        }
 
@@ -239,21 +242,21 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        switch (eventcause) {
        case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
-               dev_err(adapter->dev,
-                       "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
                break;
        case EVENT_LINK_SENSED:
-               dev_dbg(adapter->dev, "event: LINK_SENSED\n");
+               mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n");
                if (!netif_carrier_ok(priv->netdev))
                        netif_carrier_on(priv->netdev);
                mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
                break;
 
        case EVENT_DEAUTHENTICATED:
-               dev_dbg(adapter->dev, "event: Deauthenticated\n");
+               mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n");
                if (priv->wps.session_enable) {
-                       dev_dbg(adapter->dev,
-                               "info: receive deauth event in wps session\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: receive deauth event in wps session\n");
                        break;
                }
                adapter->dbg.num_event_deauth++;
@@ -265,10 +268,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_DISASSOCIATED:
-               dev_dbg(adapter->dev, "event: Disassociated\n");
+               mwifiex_dbg(adapter, EVENT, "event: Disassociated\n");
                if (priv->wps.session_enable) {
-                       dev_dbg(adapter->dev,
-                               "info: receive disassoc event in wps session\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: receive disassoc event in wps session\n");
                        break;
                }
                adapter->dbg.num_event_disassoc++;
@@ -280,7 +283,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_LINK_LOST:
-               dev_dbg(adapter->dev, "event: Link lost\n");
+               mwifiex_dbg(adapter, EVENT, "event: Link lost\n");
                adapter->dbg.num_event_link_lost++;
                if (priv->media_connected) {
                        reason_code =
@@ -290,7 +293,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_PS_SLEEP:
-               dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
 
                adapter->ps_state = PS_STATE_PRE_SLEEP;
 
@@ -298,12 +301,12 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_PS_AWAKE:
-               dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
                if (!adapter->pps_uapsd_mode &&
                    priv->media_connected && adapter->sleep_period.period) {
                                adapter->pps_uapsd_mode = true;
-                               dev_dbg(adapter->dev,
-                                       "event: PPS/UAPSD mode activated\n");
+                               mwifiex_dbg(adapter, EVENT,
+                                           "event: PPS/UAPSD mode activated\n");
                }
                adapter->tx_lock_flag = false;
                if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
@@ -333,26 +336,26 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        case EVENT_DEEP_SLEEP_AWAKE:
                adapter->if_ops.wakeup_complete(adapter);
-               dev_dbg(adapter->dev, "event: DS_AWAKE\n");
+               mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n");
                if (adapter->is_deep_sleep)
                        adapter->is_deep_sleep = false;
                break;
 
        case EVENT_HS_ACT_REQ:
-               dev_dbg(adapter->dev, "event: HS_ACT_REQ\n");
+               mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n");
                ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
                                       0, 0, NULL, false);
                break;
 
        case EVENT_MIC_ERR_UNICAST:
-               dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n");
+               mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n");
                cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
                                             NL80211_KEYTYPE_PAIRWISE,
                                             -1, NULL, GFP_KERNEL);
                break;
 
        case EVENT_MIC_ERR_MULTICAST:
-               dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n");
+               mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n");
                cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
                                             NL80211_KEYTYPE_GROUP,
                                             -1, NULL, GFP_KERNEL);
@@ -362,7 +365,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_ADHOC_BCN_LOST:
-               dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
+               mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n");
                priv->adhoc_is_link_sensed = false;
                mwifiex_clean_txrx(priv);
                mwifiex_stop_net_dev_queue(priv->netdev, adapter);
@@ -371,17 +374,17 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_BG_SCAN_REPORT:
-               dev_dbg(adapter->dev, "event: BGS_REPORT\n");
+               mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n");
                ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
                                       HostCmd_ACT_GEN_GET, 0, NULL, false);
                break;
 
        case EVENT_PORT_RELEASE:
-               dev_dbg(adapter->dev, "event: PORT RELEASE\n");
+               mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n");
                break;
 
        case EVENT_EXT_SCAN_REPORT:
-               dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
                if (adapter->ext_scan)
                        ret = mwifiex_handle_event_ext_scan_report(priv,
                                                adapter->event_skb->data);
@@ -389,7 +392,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_WMM_STATUS_CHANGE:
-               dev_dbg(adapter->dev, "event: WMM status changed\n");
+               mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n");
                ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
                                       0, 0, NULL, false);
                break;
@@ -401,13 +404,13 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                                 HostCmd_ACT_GEN_GET, 0, NULL, false);
                priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
-               dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n");
+               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n");
                break;
        case EVENT_SNR_LOW:
-               dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n");
+               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n");
                break;
        case EVENT_MAX_FAIL:
-               dev_dbg(adapter->dev, "event: MAX_FAIL\n");
+               mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n");
                break;
        case EVENT_RSSI_HIGH:
                cfg80211_cqm_rssi_notify(priv->netdev,
@@ -416,47 +419,47 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                                 HostCmd_ACT_GEN_GET, 0, NULL, false);
                priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
-               dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n");
+               mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n");
                break;
        case EVENT_SNR_HIGH:
-               dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n");
+               mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n");
                break;
        case EVENT_DATA_RSSI_LOW:
-               dev_dbg(adapter->dev, "event: Data RSSI_LOW\n");
+               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n");
                break;
        case EVENT_DATA_SNR_LOW:
-               dev_dbg(adapter->dev, "event: Data SNR_LOW\n");
+               mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n");
                break;
        case EVENT_DATA_RSSI_HIGH:
-               dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n");
+               mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n");
                break;
        case EVENT_DATA_SNR_HIGH:
-               dev_dbg(adapter->dev, "event: Data SNR_HIGH\n");
+               mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n");
                break;
        case EVENT_LINK_QUALITY:
-               dev_dbg(adapter->dev, "event: Link Quality\n");
+               mwifiex_dbg(adapter, EVENT, "event: Link Quality\n");
                break;
        case EVENT_PRE_BEACON_LOST:
-               dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n");
+               mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n");
                break;
        case EVENT_IBSS_COALESCED:
-               dev_dbg(adapter->dev, "event: IBSS_COALESCED\n");
+               mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n");
                ret = mwifiex_send_cmd(priv,
                                HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
                                HostCmd_ACT_GEN_GET, 0, NULL, false);
                break;
        case EVENT_ADDBA:
-               dev_dbg(adapter->dev, "event: ADDBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
                mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
                                 HostCmd_ACT_GEN_SET, 0,
                                 adapter->event_body, false);
                break;
        case EVENT_DELBA:
-               dev_dbg(adapter->dev, "event: DELBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
                mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
                break;
        case EVENT_BA_STREAM_TIEMOUT:
-               dev_dbg(adapter->dev, "event:  BA Stream timeout\n");
+               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
                mwifiex_11n_ba_stream_timeout(priv,
                                              (struct host_cmd_ds_11n_batimeout
                                               *)
@@ -464,28 +467,31 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
        case EVENT_AMSDU_AGGR_CTRL:
                ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
-               dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
 
                adapter->tx_buf_size =
                                min_t(u16, adapter->curr_tx_buf_size, ctrl);
-               dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
-                       adapter->tx_buf_size);
+               mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n",
+                           adapter->tx_buf_size);
                break;
 
        case EVENT_WEP_ICV_ERR:
-               dev_dbg(adapter->dev, "event: WEP ICV error\n");
+               mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n");
                break;
 
        case EVENT_BW_CHANGE:
-               dev_dbg(adapter->dev, "event: BW Change\n");
+               mwifiex_dbg(adapter, EVENT, "event: BW Change\n");
                break;
 
        case EVENT_HOSTWAKE_STAIE:
-               dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: HOSTWAKE_STAIE %d\n", eventcause);
                break;
 
        case EVENT_REMAIN_ON_CHAN_EXPIRED:
-               dev_dbg(adapter->dev, "event: Remain on channel expired\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "event: Remain on channel expired\n");
                cfg80211_remain_on_channel_expired(&priv->wdev,
                                                   priv->roc_cfg.cookie,
                                                   &priv->roc_cfg.chan,
@@ -496,7 +502,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_CHANNEL_SWITCH_ANN:
-               dev_dbg(adapter->dev, "event: Channel Switch Announcement\n");
+               mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n");
                priv->csa_expire_time =
                                jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
                priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
@@ -511,23 +517,23 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_TX_STATUS_REPORT:
-               dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
                mwifiex_parse_tx_status_event(priv, adapter->event_body);
                break;
 
        case EVENT_CHANNEL_REPORT_RDY:
-               dev_dbg(adapter->dev, "event: Channel Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
                ret = mwifiex_11h_handle_chanrpt_ready(priv,
                                                       adapter->event_skb);
                break;
        case EVENT_RADAR_DETECTED:
-               dev_dbg(adapter->dev, "event: Radar detected\n");
+               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
                ret = mwifiex_11h_handle_radar_detected(priv,
                                                        adapter->event_skb);
                break;
        default:
-               dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
-                       eventcause);
+               mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
+                           eventcause);
                break;
        }
 
index a0bc26c5eac09fdaaccdb583ef52945f68f123dc..d8b7d9c20450f704988c22e26ce81656d4e1a621 100644 (file)
@@ -66,7 +66,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
        if (status <= 0) {
                if (status == 0)
                        status = -ETIMEDOUT;
-               dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd_wait_q terminated: %d\n", status);
                mwifiex_cancel_all_pending_cmd(adapter);
                return status;
        }
@@ -93,7 +94,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
        old_pkt_filter = priv->curr_pkt_filter;
 
        if (mcast_list->mode == MWIFIEX_PROMISC_MODE) {
-               dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Enable Promiscuous mode\n");
                priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
                priv->curr_pkt_filter &=
                        ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
@@ -101,16 +103,16 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
                /* Multicast */
                priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
                if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
-                       dev_dbg(priv->adapter->dev,
-                               "info: Enabling All Multicast!\n");
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Enabling All Multicast!\n");
                        priv->curr_pkt_filter |=
                                HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
                } else {
                        priv->curr_pkt_filter &=
                                ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-                       dev_dbg(priv->adapter->dev,
-                               "info: Set multicast list=%d\n",
-                               mcast_list->num_multicast_addr);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: Set multicast list=%d\n",
+                                   mcast_list->num_multicast_addr);
                        /* Send multicast addresses to firmware */
                        ret = mwifiex_send_cmd(priv,
                                               HostCmd_CMD_MAC_MULTICAST_ADR,
@@ -118,9 +120,9 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
                                               mcast_list, false);
                }
        }
-       dev_dbg(priv->adapter->dev,
-               "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",
-              old_pkt_filter, priv->curr_pkt_filter);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",
+                   old_pkt_filter, priv->curr_pkt_filter);
        if (old_pkt_filter != priv->curr_pkt_filter) {
                ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
                                       HostCmd_ACT_GEN_SET,
@@ -153,7 +155,8 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
        rcu_read_unlock();
 
        if (!beacon_ie) {
-               dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           " failed to alloc beacon_ie\n");
                return -ENOMEM;
        }
 
@@ -167,7 +170,8 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
        bss_desc->bss_band = bss_priv->band;
        bss_desc->fw_tsf = bss_priv->fw_tsf;
        if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
-               dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "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;
@@ -221,8 +225,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
 
        if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) {
                rcu_read_unlock();
-               wiphy_dbg(priv->wdev.wiphy,
-                         "11D: skip setting domain info in FW\n");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "11D: skip setting domain info in FW\n");
                return 0;
        }
        memcpy(priv->adapter->country_code, &country_ie[2], 2);
@@ -243,8 +247,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               wiphy_err(priv->adapter->wiphy,
-                         "11D: setting domain info in FW\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: setting domain info in FW fail\n");
                return -1;
        }
 
@@ -306,14 +310,15 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 
                if (mwifiex_11h_get_csa_closed_channel(priv) ==
                                                        (u8)bss_desc->channel) {
-                       dev_err(adapter->dev,
-                               "Attempt to reconnect on csa closed chan(%d)\n",
-                               bss_desc->channel);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Attempt to reconnect on csa closed chan(%d)\n",
+                                   bss_desc->channel);
                        goto done;
                }
 
-               dev_dbg(adapter->dev, "info: SSID found in scan list ... "
-                                     "associating...\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: SSID found in scan list ...\t"
+                           "associating...\n");
 
                mwifiex_stop_net_dev_queue(priv->netdev, adapter);
                if (netif_carrier_ok(priv->netdev))
@@ -355,15 +360,17 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                        netif_carrier_off(priv->netdev);
 
                if (!ret) {
-                       dev_dbg(adapter->dev, "info: network found in scan"
-                                                       " list. Joining...\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: network found in scan\t"
+                                   " list. Joining...\n");
                        ret = mwifiex_adhoc_join(priv, bss_desc);
                        if (bss)
                                cfg80211_put_bss(priv->adapter->wiphy, bss);
                } else {
-                       dev_dbg(adapter->dev, "info: Network not found in "
-                               "the list, creating adhoc with ssid = %s\n",
-                               req_ssid->ssid);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Network not found in\t"
+                                   "the list, creating adhoc with ssid = %s\n",
+                                   req_ssid->ssid);
                        ret = mwifiex_adhoc_start(priv, req_ssid);
                }
        }
@@ -398,8 +405,9 @@ int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
        switch (action) {
        case HostCmd_ACT_GEN_SET:
                if (adapter->pps_uapsd_mode) {
-                       dev_dbg(adapter->dev, "info: Host Sleep IOCTL"
-                               " is blocked in UAPSD/PPS mode\n");
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: Host Sleep IOCTL\t"
+                                   "is blocked in UAPSD/PPS mode\n");
                        status = -1;
                        break;
                }
@@ -496,7 +504,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
        }
 
        if (adapter->hs_activated) {
-               dev_dbg(adapter->dev, "cmd: HS Already activated\n");
+               mwifiex_dbg(adapter, CMD,
+                           "cmd: HS Already activated\n");
                return true;
        }
 
@@ -512,14 +521,16 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
                                                   MWIFIEX_BSS_ROLE_STA),
                                  HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD,
                                  &hscfg)) {
-               dev_err(adapter->dev, "IOCTL request HS enable failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "IOCTL request HS enable failed\n");
                return false;
        }
 
        if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q,
                                             adapter->hs_activate_wait_q_woken,
                                             (10 * HZ)) <= 0) {
-               dev_err(adapter->dev, "hs_activate_wait_q terminated\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "hs_activate_wait_q terminated\n");
                return false;
        }
 
@@ -639,10 +650,11 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
                dbm = (u16) power_cfg->power_level;
                if ((dbm < priv->min_tx_power_level) ||
                    (dbm > priv->max_tx_power_level)) {
-                       dev_err(priv->adapter->dev, "txpower value %d dBm"
-                               " is out of range (%d dBm-%d dBm)\n",
-                               dbm, priv->min_tx_power_level,
-                               priv->max_tx_power_level);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "txpower value %d dBm\t"
+                                   "is out of range (%d dBm-%d dBm)\n",
+                                   dbm, priv->min_tx_power_level,
+                                   priv->max_tx_power_level);
                        return -1;
                }
        }
@@ -741,14 +753,15 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
 {
        if (ie_len) {
                if (ie_len > sizeof(priv->wpa_ie)) {
-                       dev_err(priv->adapter->dev,
-                               "failed to copy WPA IE, too big\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "failed to copy WPA IE, too big\n");
                        return -1;
                }
                memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
                priv->wpa_ie_len = (u8) ie_len;
-               dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
-                       priv->wpa_ie_len, priv->wpa_ie[0]);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set Wpa_ie_len=%d IE=%#x\n",
+                           priv->wpa_ie_len, priv->wpa_ie[0]);
 
                if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
                        priv->sec_info.wpa_enabled = true;
@@ -761,8 +774,9 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
        } else {
                memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie));
                priv->wpa_ie_len = 0;
-               dev_dbg(priv->adapter->dev, "info: reset wpa_ie_len=%d IE=%#x\n",
-                       priv->wpa_ie_len, priv->wpa_ie[0]);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: reset wpa_ie_len=%d IE=%#x\n",
+                           priv->wpa_ie_len, priv->wpa_ie[0]);
                priv->sec_info.wpa_enabled = false;
                priv->sec_info.wpa2_enabled = false;
        }
@@ -782,23 +796,24 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,
 {
        if (ie_len) {
                if (ie_len > sizeof(priv->wapi_ie)) {
-                       dev_dbg(priv->adapter->dev,
-                               "info: failed to copy WAPI IE, too big\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "info: failed to copy WAPI IE, too big\n");
                        return -1;
                }
                memcpy(priv->wapi_ie, ie_data_ptr, ie_len);
                priv->wapi_ie_len = ie_len;
-               dev_dbg(priv->adapter->dev, "cmd: Set wapi_ie_len=%d IE=%#x\n",
-                       priv->wapi_ie_len, priv->wapi_ie[0]);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set wapi_ie_len=%d IE=%#x\n",
+                           priv->wapi_ie_len, priv->wapi_ie[0]);
 
                if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY)
                        priv->sec_info.wapi_enabled = true;
        } else {
                memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie));
                priv->wapi_ie_len = ie_len;
-               dev_dbg(priv->adapter->dev,
-                       "info: Reset wapi_ie_len=%d IE=%#x\n",
-                      priv->wapi_ie_len, priv->wapi_ie[0]);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Reset wapi_ie_len=%d IE=%#x\n",
+                           priv->wapi_ie_len, priv->wapi_ie[0]);
                priv->sec_info.wapi_enabled = false;
        }
        return 0;
@@ -816,8 +831,8 @@ static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
 {
        if (ie_len) {
                if (ie_len > MWIFIEX_MAX_VSIE_LEN) {
-                       dev_dbg(priv->adapter->dev,
-                               "info: failed to copy WPS IE, too big\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "info: failed to copy WPS IE, too big\n");
                        return -1;
                }
 
@@ -827,13 +842,14 @@ static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
 
                memcpy(priv->wps_ie, ie_data_ptr, ie_len);
                priv->wps_ie_len = ie_len;
-               dev_dbg(priv->adapter->dev, "cmd: Set wps_ie_len=%d IE=%#x\n",
-                       priv->wps_ie_len, priv->wps_ie[0]);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: Set wps_ie_len=%d IE=%#x\n",
+                           priv->wps_ie_len, priv->wps_ie[0]);
        } else {
                kfree(priv->wps_ie);
                priv->wps_ie_len = ie_len;
-               dev_dbg(priv->adapter->dev,
-                       "info: Reset wps_ie_len=%d\n", priv->wps_ie_len);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: Reset wps_ie_len=%d\n", priv->wps_ie_len);
        }
        return 0;
 }
@@ -877,8 +893,8 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
                /* Copy the required key as the current key */
                wep_key = &priv->wep_key[index];
                if (!wep_key->key_length) {
-                       dev_err(adapter->dev,
-                               "key not set, so cannot enable it\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "key not set, so cannot enable it\n");
                        return -1;
                }
 
@@ -955,7 +971,8 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv,
 
        /* Current driver only supports key length of up to 32 bytes */
        if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) {
-               dev_err(priv->adapter->dev, "key length too long\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "key length too long\n");
                return -1;
        }
 
@@ -1042,7 +1059,7 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
 
        snprintf(version, max_len, driver_version, fw_ver);
 
-       dev_dbg(adapter->dev, "info: MWIFIEX VERSION: %s\n", version);
+       mwifiex_dbg(adapter, MSG, "info: MWIFIEX VERSION: %s\n", version);
 
        return 0;
 }
@@ -1130,7 +1147,8 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
        }
        if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN,
                             action, 0, &roc_cfg, true)) {
-               dev_err(priv->adapter->dev, "failed to remain on channel\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "failed to remain on channel\n");
                return -1;
        }
 
@@ -1315,8 +1333,8 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
                if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
                    (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
                        priv->wps.session_enable = true;
-                       dev_dbg(priv->adapter->dev,
-                               "info: WPS Session Enabled.\n");
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: WPS Session Enabled.\n");
                        ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len);
                }
 
@@ -1363,7 +1381,8 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
                memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter));
                if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) {
                        adapter->arp_filter_size = 0;
-                       dev_err(adapter->dev, "invalid ARP filter size\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "invalid ARP filter size\n");
                        return -1;
                } else {
                        memcpy(adapter->arp_filter, gen_ie->ie_data,
@@ -1372,7 +1391,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
                }
                break;
        default:
-               dev_err(adapter->dev, "invalid IE type\n");
+               mwifiex_dbg(adapter, ERROR, "invalid IE type\n");
                return -1;
        }
        return 0;
index b8729c9394e92553b12301317c9b281209e248c6..d4d4cb1ce95b868f6e052b69b2f748b98a4b2b7e 100644 (file)
@@ -141,7 +141,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 
        if (priv->hs2_enabled &&
            mwifiex_discard_gratuitous_arp(priv, skb)) {
-               dev_dbg(priv->adapter->dev, "Bypassed Gratuitous ARP\n");
+               mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
                dev_kfree_skb_any(skb);
                return 0;
        }
@@ -166,7 +166,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 
        ret = mwifiex_recv_packet(priv, skb);
        if (ret == -1)
-               dev_err(priv->adapter->dev, "recv packet failed\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "recv packet failed\n");
 
        return ret;
 }
@@ -203,9 +204,9 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
        rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
 
        if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
-               dev_err(adapter->dev,
-                       "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
-                       skb->len, rx_pkt_offset, rx_pkt_length);
+               mwifiex_dbg(adapter, ERROR,
+                           "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
+                           skb->len, rx_pkt_offset, rx_pkt_length);
                priv->stats.rx_dropped++;
                dev_kfree_skb_any(skb);
                return ret;
@@ -214,7 +215,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
        if (rx_pkt_type == PKT_TYPE_MGMT) {
                ret = mwifiex_process_mgmt_packet(priv, skb);
                if (ret)
-                       dev_err(adapter->dev, "Rx of mgmt packet failed");
+                       mwifiex_dbg(adapter, ERROR, "Rx of mgmt packet failed");
                dev_kfree_skb_any(skb);
                return ret;
        }
index 5ce2d9a4f9193a34e9c197d63579b8aba9756d81..355ac5904fac1174e0ee200dcda012f06313a963 100644 (file)
@@ -53,7 +53,8 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
                       INTF_HEADER_LEN;
 
        if (!skb->len) {
-               dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
+               mwifiex_dbg(adapter, ERROR,
+                           "Tx: bad packet length: %d\n", skb->len);
                tx_info->status_code = -1;
                return skb->data;
        }
@@ -184,21 +185,24 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
        switch (ret) {
        case -EBUSY:
                dev_kfree_skb_any(skb);
-               dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n",
-                       __func__, ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: host_to_card failed: ret=%d\n",
+                           __func__, ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                break;
        case -1:
                adapter->data_sent = false;
                dev_kfree_skb_any(skb);
-               dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n",
-                       __func__, ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: host_to_card failed: ret=%d\n",
+                           __func__, ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                break;
        case 0:
                dev_kfree_skb_any(skb);
-               dev_dbg(adapter->dev, "data: %s: host_to_card succeeded\n",
-                       __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: host_to_card succeeded\n",
+                           __func__);
                adapter->tx_lock_flag = true;
                break;
        case -EINPROGRESS:
index 275a476f0dc76c2d29c9145643311f6131d6b02f..2faa1bc42abee2eb838d65c6c75c33a243f53875 100644 (file)
@@ -37,7 +37,7 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
        u32 tid;
        u8 tid_down;
 
-       dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
+       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
        spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
 
        skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
@@ -94,7 +94,7 @@ static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
        unsigned long flags;
        int i;
 
-       dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
+       mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);
        spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
 
        for (i = 0; i < MAX_NUM_TID; i++) {
@@ -132,8 +132,8 @@ mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
        supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
 
        if (skb_tailroom(skb) < rates_size + 4) {
-               dev_err(priv->adapter->dev,
-                       "Insuffient space while adding rates\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Insuffient space while adding rates\n");
                return -ENOMEM;
        }
 
@@ -199,8 +199,8 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
 
        sta_ptr = mwifiex_get_sta_entry(priv, mac);
        if (unlikely(!sta_ptr)) {
-               dev_warn(priv->adapter->dev,
-                        "TDLS peer station not found in list\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "TDLS peer station not found in list\n");
                return -1;
        }
 
@@ -247,15 +247,16 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
 
        sta_ptr = mwifiex_get_sta_entry(priv, mac);
        if (unlikely(!sta_ptr)) {
-               dev_warn(adapter->dev, "TDLS peer station not found in list\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "TDLS peer station not found in list\n");
                return -1;
        }
 
        if (!mwifiex_is_bss_in_11ac_mode(priv)) {
                if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
                   WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
-                       dev_dbg(adapter->dev,
-                               "TDLS peer doesn't support wider bandwidth\n");
+                       mwifiex_dbg(adapter, WARN,
+                                   "TDLS peer doesn't support wider bandwidth\n");
                        return 0;
                }
        } else {
@@ -554,7 +555,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
                tf->u.discover_req.dialog_token = dialog_token;
                break;
        default:
-               dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
                return -EINVAL;
        }
 
@@ -608,8 +609,8 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
 
        skb = dev_alloc_skb(skb_len);
        if (!skb) {
-               dev_err(priv->adapter->dev,
-                       "allocate skb failed for management frame\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
                return -ENOMEM;
        }
        skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
@@ -742,7 +743,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
                mwifiex_tdls_add_qos_capab(skb);
                break;
        default:
-               dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n");
                return -EINVAL;
        }
 
@@ -781,8 +782,8 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
 
        skb = dev_alloc_skb(skb_len);
        if (!skb) {
-               dev_err(priv->adapter->dev,
-                       "allocate skb failed for management frame\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "allocate skb failed for management frame\n");
                return -ENOMEM;
        }
 
@@ -848,8 +849,8 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
        peer = buf + ETH_ALEN;
        action = *(buf + sizeof(struct ethhdr) + 2);
-       dev_dbg(priv->adapter->dev,
-               "rx:tdls action: peer=%pM, action=%d\n", peer, action);
+       mwifiex_dbg(priv->adapter, DATA,
+                   "rx:tdls action: peer=%pM, action=%d\n", peer, action);
 
        switch (action) {
        case WLAN_TDLS_SETUP_REQUEST:
@@ -880,7 +881,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
                ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
                break;
        default:
-               dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
                return;
        }
 
@@ -967,8 +968,8 @@ mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
        sta_ptr = mwifiex_get_sta_entry(priv, peer);
 
        if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
-               dev_err(priv->adapter->dev,
-                       "link absent for peer %pM; cannot config\n", peer);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "link absent for peer %pM; cannot config\n", peer);
                return -EINVAL;
        }
 
@@ -988,8 +989,8 @@ mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
        sta_ptr = mwifiex_get_sta_entry(priv, peer);
 
        if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
-               dev_dbg(priv->adapter->dev,
-                       "Setup already in progress for peer %pM\n", peer);
+               mwifiex_dbg(priv->adapter, WARN,
+                           "Setup already in progress for peer %pM\n", peer);
                return 0;
        }
 
@@ -1046,8 +1047,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
        sta_ptr = mwifiex_get_sta_entry(priv, peer);
 
        if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
-               dev_dbg(priv->adapter->dev,
-                       "tdls: enable link %pM success\n", peer);
+               mwifiex_dbg(priv->adapter, MSG,
+                           "tdls: enable link %pM success\n", peer);
 
                sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
 
@@ -1076,8 +1077,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
                mwifiex_auto_tdls_update_peer_status(priv, peer,
                                                     TDLS_SETUP_COMPLETE);
        } else {
-               dev_dbg(priv->adapter->dev,
-                       "tdls: enable link %pM failed\n", peer);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tdls: enable link %pM failed\n", peer);
                if (sta_ptr) {
                        mwifiex_11n_cleanup_reorder_tbl(priv);
                        spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
@@ -1180,9 +1181,9 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
                tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
                if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
                                     HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
-                       dev_warn(priv->adapter->dev,
-                                "Disable link failed for TDLS peer %pM",
-                                sta_ptr->mac_addr);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Disable link failed for TDLS peer %pM",
+                                   sta_ptr->mac_addr);
        }
 
        mwifiex_del_all_sta_list(priv);
@@ -1204,9 +1205,9 @@ int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
                            (peer->failure_count <
                             MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
                                peer->tdls_status = TDLS_SETUP_INPROGRESS;
-                               dev_dbg(priv->adapter->dev,
-                                       "setup TDLS link, peer=%pM rssi=%d\n",
-                                       peer->mac_addr, peer->rssi);
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "setup TDLS link, peer=%pM rssi=%d\n",
+                                           peer->mac_addr, peer->rssi);
 
                                cfg80211_tdls_oper_request(priv->netdev,
                                                           peer->mac_addr,
@@ -1272,8 +1273,8 @@ void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
                tdls_peer->rssi_jiffies = jiffies;
                INIT_LIST_HEAD(&tdls_peer->list);
                list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
-               dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n",
-                       mac);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "Add auto TDLS peer= %pM to list\n", mac);
        }
 
        spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
@@ -1341,8 +1342,8 @@ void mwifiex_check_auto_tdls(unsigned long context)
                return;
 
        if (!priv->auto_tdls_timer_active) {
-               dev_dbg(priv->adapter->dev,
-                       "auto TDLS timer inactive; return");
+               mwifiex_dbg(priv->adapter, INFO,
+                           "auto TDLS timer inactive; return");
                return;
        }
 
@@ -1368,9 +1369,9 @@ void mwifiex_check_auto_tdls(unsigned long context)
                     !tdls_peer->rssi) &&
                    tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) {
                        tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
-                       dev_dbg(priv->adapter->dev,
-                               "teardown TDLS link,peer=%pM rssi=%d\n",
-                               tdls_peer->mac_addr, -tdls_peer->rssi);
+                       mwifiex_dbg(priv->adapter, MSG,
+                                   "teardown TDLS link,peer=%pM rssi=%d\n",
+                                   tdls_peer->mac_addr, -tdls_peer->rssi);
                        tdls_peer->do_discover = true;
                        priv->check_tdls_tx = true;
                        cfg80211_tdls_oper_request(priv->netdev,
@@ -1384,9 +1385,10 @@ void mwifiex_check_auto_tdls(unsigned long context)
                           MWIFIEX_TDLS_MAX_FAIL_COUNT) {
                                priv->check_tdls_tx = true;
                                tdls_peer->do_setup = true;
-                               dev_dbg(priv->adapter->dev,
-                                       "check TDLS with peer=%pM rssi=%d\n",
-                                       tdls_peer->mac_addr, -tdls_peer->rssi);
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "check TDLS with peer=%pM\t"
+                                           "rssi=%d\n", tdls_peer->mac_addr,
+                                           tdls_peer->rssi);
                }
        }
        spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
index a245f444aeec17e23c027b60d027239050fb4497..28dcc84a34d2b2c1878cace213c8893b033c0580 100644 (file)
@@ -50,11 +50,15 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
                priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 
        if (!priv) {
-               dev_err(adapter->dev, "data: priv not found. Drop RX packet\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "data: priv not found. Drop RX packet\n");
                dev_kfree_skb_any(skb);
                return -1;
        }
 
+       mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
+                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
+
        memset(rx_info, 0, sizeof(*rx_info));
        rx_info->bss_num = priv->bss_num;
        rx_info->bss_type = priv->bss_type;
@@ -112,10 +116,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
                                                           skb, tx_param);
                }
        }
+       mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
+                        min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
 
        switch (ret) {
        case -ENOSR:
-               dev_dbg(adapter->dev, "data: -ENOSR is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
                break;
        case -EBUSY:
                if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
@@ -124,13 +130,14 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
                                if (local_tx_pd)
                                        local_tx_pd->flags = 0;
                }
-               dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
                break;
        case -1:
                if (adapter->iface_type != MWIFIEX_PCIE)
                        adapter->data_sent = false;
-               dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
-                       ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "mwifiex_write_data_async failed: 0x%X\n",
+                           ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                mwifiex_write_data_complete(adapter, skb, 0, ret);
                break;
@@ -162,7 +169,8 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
        priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
                                      tx_info->bss_type);
        if (!priv) {
-               dev_err(adapter->dev, "data: priv not found. Drop TX packet\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "data: priv not found. Drop TX packet\n");
                adapter->dbg.num_tx_host_to_card_failure++;
                mwifiex_write_data_complete(adapter, skb, 0, 0);
                return ret;
@@ -187,7 +195,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
        }
        switch (ret) {
        case -ENOSR:
-               dev_err(adapter->dev, "data: -ENOSR is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
                break;
        case -EBUSY:
                if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
@@ -202,13 +210,13 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
                        atomic_add(tx_info->aggr_num, &adapter->tx_queued);
                else
                        atomic_inc(&adapter->tx_queued);
-               dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
                break;
        case -1:
                if (adapter->iface_type != MWIFIEX_PCIE)
                        adapter->data_sent = false;
-               dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
-                       ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "mwifiex_write_data_async failed: 0x%X\n", ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                mwifiex_write_data_complete(adapter, skb, 0, ret);
                break;
@@ -319,7 +327,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
                txq = netdev_get_tx_queue(priv->netdev, index);
                if (netif_tx_queue_stopped(txq)) {
                        netif_tx_wake_queue(txq);
-                       dev_dbg(adapter->dev, "wake queue: %d\n", index);
+                       mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
                }
        }
 done:
index 3d0281190b9dc817eefbddc9ca13550c08147135..a4ae28353b6d8bb2fd80c977aad8a7c06d78d6a3 100644 (file)
@@ -184,8 +184,8 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
                        bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
                        break;
                default:
-                       dev_warn(priv->adapter->dev,
-                                "Unsupported RX-STBC, default to 2x2\n");
+                       mwifiex_dbg(priv->adapter, WARN,
+                                   "Unsupported RX-STBC, default to 2x2\n");
                        bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
                        bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
                        break;
@@ -767,8 +767,8 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
                        return -1;
                break;
        default:
-               dev_err(priv->adapter->dev,
-                       "PREP_CMD: unknown cmd %#x\n", cmd_no);
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "PREP_CMD: unknown cmd %#x\n", cmd_no);
                return -1;
        }
 
@@ -806,24 +806,28 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
                             struct mwifiex_uap_bss_param *bss_cfg)
 {
        if (mwifiex_del_mgmt_ies(priv))
-               dev_err(priv->adapter->dev, "Failed to delete mgmt IEs!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to delete mgmt IEs!\n");
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-               dev_err(priv->adapter->dev, "Failed to stop the BSS\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to stop the BSS\n");
                return -1;
        }
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
                             HostCmd_ACT_GEN_SET,
                             UAP_BSS_PARAMS_I, bss_cfg, false)) {
-               dev_err(priv->adapter->dev, "Failed to set the SSID\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to set the SSID\n");
                return -1;
        }
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-               dev_err(priv->adapter->dev, "Failed to start the BSS\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to start the BSS\n");
                return -1;
        }
 
index f4794cdc36d229612931a22c85e6524171afcb3b..06ce3fe660f138d51873838eda532207d9665004 100644 (file)
@@ -80,8 +80,8 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 
                node = mwifiex_add_sta_entry(priv, event->sta_addr);
                if (!node) {
-                       dev_warn(adapter->dev,
-                                "could not create station entry!\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not create station entry!\n");
                        return -1;
                }
 
@@ -128,7 +128,8 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
                break;
        case EVENT_UAP_BSS_START:
-               dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
                memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
                       ETH_ALEN);
                if (priv->hist_data)
@@ -136,50 +137,53 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
        case EVENT_UAP_MIC_COUNTERMEASURES:
                /* For future development */
-               dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
                break;
        case EVENT_AMSDU_AGGR_CTRL:
                ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
-               dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
 
                if (priv->media_connected) {
                        adapter->tx_buf_size =
                                min_t(u16, adapter->curr_tx_buf_size, ctrl);
-                       dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
-                               adapter->tx_buf_size);
+                       mwifiex_dbg(adapter, EVENT,
+                                   "event: tx_buf_size %d\n",
+                                   adapter->tx_buf_size);
                }
                break;
        case EVENT_ADDBA:
-               dev_dbg(adapter->dev, "event: ADDBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
                if (priv->media_connected)
                        mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
                                         HostCmd_ACT_GEN_SET, 0,
                                         adapter->event_body, false);
                break;
        case EVENT_DELBA:
-               dev_dbg(adapter->dev, "event: DELBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
                if (priv->media_connected)
                        mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
                break;
        case EVENT_BA_STREAM_TIEMOUT:
-               dev_dbg(adapter->dev, "event:  BA Stream timeout\n");
+               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
                if (priv->media_connected) {
                        ba_timeout = (void *)adapter->event_body;
                        mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
                }
                break;
        case EVENT_EXT_SCAN_REPORT:
-               dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
                if (adapter->ext_scan)
                        return mwifiex_handle_event_ext_scan_report(priv,
                                                adapter->event_skb->data);
                break;
        case EVENT_TX_STATUS_REPORT:
-               dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
                mwifiex_parse_tx_status_event(priv, adapter->event_body);
                break;
        case EVENT_PS_SLEEP:
-               dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
 
                adapter->ps_state = PS_STATE_PRE_SLEEP;
 
@@ -187,12 +191,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_PS_AWAKE:
-               dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
                if (!adapter->pps_uapsd_mode &&
                    priv->media_connected && adapter->sleep_period.period) {
                                adapter->pps_uapsd_mode = true;
-                               dev_dbg(adapter->dev,
-                                       "event: PPS/UAPSD mode activated\n");
+                               mwifiex_dbg(adapter, EVENT,
+                                           "event: PPS/UAPSD mode activated\n");
                }
                adapter->tx_lock_flag = false;
                if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
@@ -218,16 +222,16 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_CHANNEL_REPORT_RDY:
-               dev_dbg(adapter->dev, "event: Channel Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
                mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
                break;
        case EVENT_RADAR_DETECTED:
-               dev_dbg(adapter->dev, "event: Radar detected\n");
+               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
                mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
                break;
        default:
-               dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
-                       eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: unknown event id: %#x\n", eventcause);
                break;
        }
 
index 38ac4d74c486c8d080d1c87c78e54a74c63e296c..61c52fdf945d42140c000e2c8a298f1f4d08dc60 100644 (file)
@@ -103,8 +103,8 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 
        if ((atomic_read(&adapter->pending_bridged_pkts) >=
                                             MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
-               dev_err(priv->adapter->dev,
-                       "Tx: Bridge packet limit reached. Drop packet!\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Tx: Bridge packet limit reached. Drop packet!\n");
                kfree_skb(skb);
                mwifiex_uap_cleanup_tx_queues(priv);
                return;
@@ -153,15 +153,15 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        skb_pull(skb, hdr_chop);
 
        if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
-               dev_dbg(priv->adapter->dev,
-                       "data: Tx: insufficient skb headroom %d\n",
-                       skb_headroom(skb));
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "data: Tx: insufficient skb headroom %d\n",
+                           skb_headroom(skb));
                /* Insufficient skb headroom - allocate a new skb */
                new_skb =
                        skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
                if (unlikely(!new_skb)) {
-                       dev_err(priv->adapter->dev,
-                               "Tx: cannot allocate new_skb\n");
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Tx: cannot allocate new_skb\n");
                        kfree_skb(skb);
                        priv->stats.tx_dropped++;
                        return;
@@ -169,8 +169,9 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 
                kfree_skb(skb);
                skb = new_skb;
-               dev_dbg(priv->adapter->dev, "info: new skb headroom %d\n",
-                       skb_headroom(skb));
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: new skb headroom %d\n",
+                           skb_headroom(skb));
        }
 
        tx_info = MWIFIEX_SKB_TXCB(skb);
@@ -225,7 +226,8 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
 
        /* don't do packet forwarding in disconnected state */
        if (!priv->media_connected) {
-               dev_err(adapter->dev, "drop packet in disconnected state.\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "drop packet in disconnected state.\n");
                dev_kfree_skb_any(skb);
                return 0;
        }
@@ -275,10 +277,10 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
 
        if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
             le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
-               dev_err(adapter->dev,
-                       "wrong rx packet: len=%d, offset=%d, length=%d\n",
-                       skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
-                       le16_to_cpu(uap_rx_pd->rx_pkt_length));
+               mwifiex_dbg(adapter, ERROR,
+                           "wrong rx packet: len=%d, offset=%d, length=%d\n",
+                           skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
+                           le16_to_cpu(uap_rx_pd->rx_pkt_length));
                priv->stats.rx_dropped++;
                dev_kfree_skb_any(skb);
                return 0;
@@ -287,7 +289,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
        if (rx_pkt_type == PKT_TYPE_MGMT) {
                ret = mwifiex_process_mgmt_packet(priv, skb);
                if (ret)
-                       dev_err(adapter->dev, "Rx of mgmt packet failed");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Rx of mgmt packet failed");
                dev_kfree_skb_any(skb);
                return ret;
        }
@@ -354,7 +357,8 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
                       INTF_HEADER_LEN;
 
        if (!skb->len) {
-               dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
+               mwifiex_dbg(adapter, ERROR,
+                           "Tx: bad packet length: %d\n", skb->len);
                tx_info->status_code = -1;
                return skb->data;
        }
index fd8027f200a0ddd61c178ee1f7107e7e0931c1c1..aada93425f806a74b481e937d7f25fab5a68d4d3 100644 (file)
@@ -60,7 +60,6 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size);
 static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                            struct sk_buff *skb, u8 ep)
 {
-       struct device *dev = adapter->dev;
        u32 recv_type;
        __le32 tmp;
        int ret;
@@ -69,13 +68,15 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                mwifiex_process_hs_config(adapter);
 
        if (skb->len < INTF_HEADER_LEN) {
-               dev_err(dev, "%s: invalid skb->len\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: invalid skb->len\n", __func__);
                return -1;
        }
 
        switch (ep) {
        case MWIFIEX_USB_EP_CMD_EVENT:
-               dev_dbg(dev, "%s: EP_CMD_EVENT\n", __func__);
+               mwifiex_dbg(adapter, EVENT,
+                           "%s: EP_CMD_EVENT\n", __func__);
                skb_copy_from_linear_data(skb, &tmp, INTF_HEADER_LEN);
                recv_type = le32_to_cpu(tmp);
                skb_pull(skb, INTF_HEADER_LEN);
@@ -83,11 +84,12 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                switch (recv_type) {
                case MWIFIEX_USB_TYPE_CMD:
                        if (skb->len > MWIFIEX_SIZE_OF_CMD_BUFFER) {
-                               dev_err(dev, "CMD: skb->len too large\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "CMD: skb->len too large\n");
                                ret = -1;
                                goto exit_restore_skb;
                        } else if (!adapter->curr_cmd) {
-                               dev_dbg(dev, "CMD: no curr_cmd\n");
+                               mwifiex_dbg(adapter, WARN, "CMD: no curr_cmd\n");
                                if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
                                        mwifiex_process_sleep_confirm_resp(
                                                        adapter, skb->data,
@@ -104,16 +106,19 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                        break;
                case MWIFIEX_USB_TYPE_EVENT:
                        if (skb->len < sizeof(u32)) {
-                               dev_err(dev, "EVENT: skb->len too small\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EVENT: skb->len too small\n");
                                ret = -1;
                                goto exit_restore_skb;
                        }
                        skb_copy_from_linear_data(skb, &tmp, sizeof(u32));
                        adapter->event_cause = le32_to_cpu(tmp);
-                       dev_dbg(dev, "event_cause %#x\n", adapter->event_cause);
+                       mwifiex_dbg(adapter, EVENT,
+                                   "event_cause %#x\n", adapter->event_cause);
 
                        if (skb->len > MAX_EVENT_SIZE) {
-                               dev_err(dev, "EVENT: event body too large\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "EVENT: event body too large\n");
                                ret = -1;
                                goto exit_restore_skb;
                        }
@@ -125,14 +130,16 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                        adapter->event_skb = skb;
                        break;
                default:
-                       dev_err(dev, "unknown recv_type %#x\n", recv_type);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "unknown recv_type %#x\n", recv_type);
                        return -1;
                }
                break;
        case MWIFIEX_USB_EP_DATA:
-               dev_dbg(dev, "%s: EP_DATA\n", __func__);
+               mwifiex_dbg(adapter, DATA, "%s: EP_DATA\n", __func__);
                if (skb->len > MWIFIEX_RX_DATA_BUF_SIZE) {
-                       dev_err(dev, "DATA: skb->len too large\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "DATA: skb->len too large\n");
                        return -1;
                }
 
@@ -141,7 +148,8 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
                atomic_inc(&adapter->rx_pending);
                break;
        default:
-               dev_err(dev, "%s: unknown endport %#x\n", __func__, ep);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: unknown endport %#x\n", __func__, ep);
                return -1;
        }
 
@@ -176,8 +184,8 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
 
        if (recv_length) {
                if (urb->status || (adapter->surprise_removed)) {
-                       dev_err(adapter->dev,
-                               "URB status is failed: %d\n", urb->status);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "URB status is failed: %d\n", urb->status);
                        /* Do not free skb in case of command ep */
                        if (card->rx_cmd_ep != context->ep)
                                dev_kfree_skb_any(skb);
@@ -190,8 +198,9 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
 
                status = mwifiex_usb_recv(adapter, skb, context->ep);
 
-               dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n",
-                       recv_length, status);
+               mwifiex_dbg(adapter, INFO,
+                           "info: recv_length=%d, status=%d\n",
+                           recv_length, status);
                if (status == -EINPROGRESS) {
                        mwifiex_queue_main_work(adapter);
 
@@ -203,8 +212,8 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
                                return;
                } else {
                        if (status == -1)
-                               dev_err(adapter->dev,
-                                       "received data processing failed!\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "received data processing failed!\n");
 
                        /* Do not free skb in case of command ep */
                        if (card->rx_cmd_ep != context->ep)
@@ -212,8 +221,8 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
                }
        } else if (urb->status) {
                if (!adapter->is_suspended) {
-                       dev_warn(adapter->dev,
-                                "Card is removed: %d\n", urb->status);
+                       mwifiex_dbg(adapter, FATAL,
+                                   "Card is removed: %d\n", urb->status);
                        adapter->surprise_removed = true;
                }
                dev_kfree_skb_any(skb);
@@ -249,14 +258,17 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
        struct mwifiex_adapter *adapter = context->adapter;
        struct usb_card_rec *card = adapter->card;
 
-       dev_dbg(adapter->dev, "%s: status: %d\n", __func__, urb->status);
+       mwifiex_dbg(adapter, INFO,
+                   "%s: status: %d\n", __func__, urb->status);
 
        if (context->ep == card->tx_cmd_ep) {
-               dev_dbg(adapter->dev, "%s: CMD\n", __func__);
+               mwifiex_dbg(adapter, CMD,
+                           "%s: CMD\n", __func__);
                atomic_dec(&card->tx_cmd_urb_pending);
                adapter->cmd_sent = false;
        } else {
-               dev_dbg(adapter->dev, "%s: DATA\n", __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "%s: DATA\n", __func__);
                atomic_dec(&card->tx_data_urb_pending);
                mwifiex_write_data_complete(adapter, context->skb, 0,
                                            urb->status ? -1 : 0);
@@ -275,8 +287,8 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
        if (card->rx_cmd_ep != ctx->ep) {
                ctx->skb = dev_alloc_skb(size);
                if (!ctx->skb) {
-                       dev_err(adapter->dev,
-                               "%s: dev_alloc_skb failed\n", __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: dev_alloc_skb failed\n", __func__);
                        return -ENOMEM;
                }
        }
@@ -291,7 +303,7 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size)
                atomic_inc(&card->rx_data_urb_pending);
 
        if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) {
-               dev_err(adapter->dev, "usb_submit_urb failed\n");
+               mwifiex_dbg(adapter, ERROR, "usb_submit_urb failed\n");
                dev_kfree_skb_any(ctx->skb);
                ctx->skb = NULL;
 
@@ -468,7 +480,8 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
        adapter = card->adapter;
 
        if (unlikely(adapter->is_suspended))
-               dev_warn(adapter->dev, "Device already suspended\n");
+               mwifiex_dbg(adapter, WARN,
+                           "Device already suspended\n");
 
        mwifiex_enable_hs(adapter);
 
@@ -519,7 +532,8 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
        adapter = card->adapter;
 
        if (unlikely(!adapter->is_suspended)) {
-               dev_warn(adapter->dev, "Device already resumed\n");
+               mwifiex_dbg(adapter, WARN,
+                           "Device already resumed\n");
                return 0;
        }
 
@@ -578,7 +592,8 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 
        mwifiex_usb_free(card);
 
-       dev_dbg(adapter->dev, "%s: removing card\n", __func__);
+       mwifiex_dbg(adapter, FATAL,
+                   "%s: removing card\n", __func__);
        mwifiex_remove_card(adapter, &add_remove_card_sem);
 
        usb_set_intfdata(intf, NULL);
@@ -608,7 +623,8 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
 
        card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!card->tx_cmd.urb) {
-               dev_err(adapter->dev, "tx_cmd.urb allocation failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "tx_cmd.urb allocation failed\n");
                return -ENOMEM;
        }
 
@@ -620,8 +636,8 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
 
                card->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
                if (!card->tx_data_list[i].urb) {
-                       dev_err(adapter->dev,
-                               "tx_data_list[] urb allocation failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "tx_data_list[] urb allocation failed\n");
                        return -ENOMEM;
                }
        }
@@ -639,15 +655,13 @@ static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
 
        card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!card->rx_cmd.urb) {
-               dev_err(adapter->dev, "rx_cmd.urb allocation failed\n");
+               mwifiex_dbg(adapter, ERROR, "rx_cmd.urb allocation failed\n");
                return -ENOMEM;
        }
 
        card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
-       if (!card->rx_cmd.skb) {
-               dev_err(adapter->dev, "rx_cmd.skb allocation failed\n");
+       if (!card->rx_cmd.skb)
                return -ENOMEM;
-       }
 
        if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
                return -1;
@@ -658,8 +672,8 @@ static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
 
                card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
                if (!card->rx_data_list[i].urb) {
-                       dev_err(adapter->dev,
-                               "rx_data_list[] urb allocation failed\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "rx_data_list[] urb allocation failed\n");
                        return -1;
                }
                if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
@@ -683,7 +697,8 @@ static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
        ret = usb_bulk_msg(card->udev, usb_sndbulkpipe(card->udev, ep), pbuf,
                           *len, &actual_length, timeout);
        if (ret) {
-               dev_err(adapter->dev, "usb_bulk_msg for tx failed: %d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "usb_bulk_msg for tx failed: %d\n", ret);
                return ret;
        }
 
@@ -702,7 +717,8 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
        ret = usb_bulk_msg(card->udev, usb_rcvbulkpipe(card->udev, ep), pbuf,
                           *len, &actual_length, timeout);
        if (ret) {
-               dev_err(adapter->dev, "usb_bulk_msg for rx failed: %d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "usb_bulk_msg for rx failed: %d\n", ret);
                return ret;
        }
 
@@ -722,13 +738,13 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
        struct urb *tx_urb;
 
        if (adapter->is_suspended) {
-               dev_err(adapter->dev,
-                       "%s: not allowed while suspended\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: not allowed while suspended\n", __func__);
                return -1;
        }
 
        if (adapter->surprise_removed) {
-               dev_err(adapter->dev, "%s: device removed\n", __func__);
+               mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__);
                return -1;
        }
 
@@ -737,7 +753,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
                return -EBUSY;
        }
 
-       dev_dbg(adapter->dev, "%s: ep=%d\n", __func__, ep);
+       mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep);
 
        if (ep == card->tx_cmd_ep) {
                context = &card->tx_cmd;
@@ -764,7 +780,8 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
                atomic_inc(&card->tx_data_urb_pending);
 
        if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
-               dev_err(adapter->dev, "%s: usb_submit_urb failed\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: usb_submit_urb failed\n", __func__);
                if (ep == card->tx_cmd_ep) {
                        atomic_dec(&card->tx_cmd_urb_pending);
                } else {
@@ -843,8 +860,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
        u8 check_winner = 1;
 
        if (!firmware) {
-               dev_err(adapter->dev,
-                       "No firmware image found! Terminating download\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "No firmware image found! Terminating download\n");
                ret = -1;
                goto fw_exit;
        }
@@ -889,8 +906,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                                                MWIFIEX_USB_EP_CMD_EVENT,
                                                MWIFIEX_USB_TIMEOUT);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "write_data_sync: failed: %d\n", ret);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write_data_sync: failed: %d\n",
+                                           ret);
                                continue;
                        }
 
@@ -902,8 +920,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                                                MWIFIEX_USB_EP_CMD_EVENT,
                                                MWIFIEX_USB_TIMEOUT);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "read_data_sync: failed: %d\n", ret);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "read_data_sync: failed: %d\n",
+                                           ret);
                                continue;
                        }
 
@@ -913,17 +932,17 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                        /* check 1st firmware block resp for highest bit set */
                        if (check_winner) {
                                if (le32_to_cpu(sync_fw.cmd) & 0x80000000) {
-                                       dev_warn(adapter->dev,
-                                                "USB is not the winner %#x\n",
-                                                sync_fw.cmd);
+                                       mwifiex_dbg(adapter, WARN,
+                                                   "USB is not the winner %#x\n",
+                                                   sync_fw.cmd);
 
                                        /* returning success */
                                        ret = 0;
                                        goto cleanup;
                                }
 
-                               dev_dbg(adapter->dev,
-                                       "USB is the winner, start to download FW\n");
+                               mwifiex_dbg(adapter, MSG,
+                                           "start to download FW...\n");
 
                                check_winner = 0;
                                break;
@@ -931,9 +950,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 
                        /* check the firmware block response for CRC errors */
                        if (sync_fw.cmd) {
-                               dev_err(adapter->dev,
-                                       "FW received block with CRC %#x\n",
-                                       sync_fw.cmd);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW received block with CRC %#x\n",
+                                           sync_fw.cmd);
                                ret = -1;
                                continue;
                        }
@@ -945,8 +964,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
        } while ((dnld_cmd != FW_HAS_LAST_BLOCK) && retries);
 
 cleanup:
-       dev_notice(adapter->dev,
-                  "info: FW download over, size %d bytes\n", tlen);
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", tlen);
 
        kfree(recv_buff);
        kfree(fwdata);
index 9482d955c3844daa5570ed09a8c5604b9fa7a4ea..370323a47ecb99d3c246b94fc86e0e3eb0f8ffde 100644 (file)
@@ -26,6 +26,8 @@
 #include "11n.h"
 
 static struct mwifiex_debug_data items[] = {
+       {"debug_mask", item_size(debug_mask),
+        item_addr(debug_mask), 1},
        {"int_counter", item_size(int_counter),
         item_addr(int_counter), 1},
        {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]),
@@ -158,7 +160,8 @@ int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
        } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {
                cmd = HostCmd_CMD_FUNC_SHUTDOWN;
        } else {
-               dev_err(priv->adapter->dev, "unsupported parameter\n");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "unsupported parameter\n");
                return -1;
        }
 
@@ -178,6 +181,7 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
        struct mwifiex_adapter *adapter = priv->adapter;
 
        if (info) {
+               info->debug_mask = adapter->debug_mask;
                memcpy(info->packets_out,
                       priv->wmm.packets_out,
                       sizeof(priv->wmm.packets_out));
@@ -336,9 +340,9 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
                action_code = *(payload + sizeof(struct ieee80211_hdr) + 1);
                if (category == WLAN_CATEGORY_PUBLIC &&
                    action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
-                       dev_dbg(priv->adapter->dev,
-                               "TDLS discovery response %pM nf=%d, snr=%d\n",
-                               ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "TDLS discovery response %pM nf=%d, snr=%d\n",
+                                   ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
                        mwifiex_auto_tdls_update_peer_signal(priv,
                                                             ieee_hdr->addr2,
                                                             rx_pd->snr,
@@ -346,8 +350,8 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
                }
                break;
        default:
-               dev_dbg(priv->adapter->dev,
-                       "unknown mgmt frame subytpe %#x\n", stype);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "unknown mgmt frame subtype %#x\n", stype);
        }
 
        return 0;
@@ -369,8 +373,8 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 
        if (!priv->mgmt_frame_mask ||
            priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
-               dev_dbg(priv->adapter->dev,
-                       "do not receive mgmt frames on uninitialized intf");
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "do not receive mgmt frames on uninitialized intf");
                return -1;
        }
 
@@ -464,13 +468,14 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
                         struct cmd_ctrl_node *cmd_node)
 {
-       dev_dbg(adapter->dev, "cmd completed: status=%d\n",
-               adapter->cmd_wait_q.status);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd completed: status=%d\n",
+                   adapter->cmd_wait_q.status);
 
        *(cmd_node->condition) = true;
 
        if (adapter->cmd_wait_q.status == -ETIMEDOUT)
-               dev_err(adapter->dev, "cmd timeout\n");
+               mwifiex_dbg(adapter, ERROR, "cmd timeout\n");
        else
                wake_up_interruptible(&adapter->cmd_wait_q.wait);
 
index 8be9d1310cde3d968cc6012993a5319d479fe01d..a8ea21c3340c73537c8f597ad6dc2d176b45f588 100644 (file)
@@ -107,7 +107,7 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
 
        ra_list->total_pkt_count = 0;
 
-       dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list);
+       mwifiex_dbg(adapter, INFO, "info: allocated ra_list %p\n", ra_list);
 
        return ra_list;
 }
@@ -150,7 +150,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
 
        for (i = 0; i < MAX_NUM_TID; ++i) {
                ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
-               dev_dbg(adapter->dev, "info: created ra_list %p\n", ra_list);
+               mwifiex_dbg(adapter, INFO,
+                           "info: created ra_list %p\n", ra_list);
 
                if (!ra_list)
                        break;
@@ -178,8 +179,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
                        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
                }
 
-               dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
-                       ra_list, ra_list->is_11n_enabled);
+               mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n",
+                           ra_list, ra_list->is_11n_enabled);
 
                if (ra_list->is_11n_enabled) {
                        ra_list->ba_pkt_count = 0;
@@ -241,11 +242,12 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
                return;
        }
 
-       dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, "
-               "qos_info Parameter Set Count=%d, Reserved=%#x\n",
-               wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap &
-               IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
-               wmm_ie->reserved);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM Parameter IE: version=%d,\t"
+                   "qos_info Parameter Set Count=%d, Reserved=%#x\n",
+                   wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap &
+                   IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
+                   wmm_ie->reserved);
 
        for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) {
                u8 ecw = wmm_ie->ac_params[num_ac].ecw_bitmap;
@@ -257,10 +259,10 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
                priv->wmm.queue_priority[ac_idx] = ac_idx;
                tmp[ac_idx] = avg_back_off;
 
-               dev_dbg(priv->adapter->dev,
-                       "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
-                       (1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1,
-                       cw_min, avg_back_off);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
+                           (1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1,
+                           cw_min, avg_back_off);
                mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]);
        }
 
@@ -333,8 +335,8 @@ mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv)
 {
        int ac_val;
 
-       dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:"
-                       "BK(0), BE(1), VI(2), VO(3)\n");
+       mwifiex_dbg(priv->adapter, INFO, "info: WMM: AC Priorities:\t"
+                   "BK(0), BE(1), VI(2), VO(3)\n");
 
        if (!priv->wmm_enabled) {
                /* WMM is not enabled, default priorities */
@@ -346,9 +348,10 @@ mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv)
                        priv->wmm.ac_down_graded_vals[ac_val]
                                = mwifiex_wmm_eval_downgrade_ac(priv,
                                                (enum mwifiex_wmm_ac_e) ac_val);
-                       dev_dbg(priv->adapter->dev,
-                               "info: WMM: AC PRIO %d maps to %d\n",
-                               ac_val, priv->wmm.ac_down_graded_vals[ac_val]);
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "info: WMM: AC PRIO %d maps to %d\n",
+                                   ac_val,
+                                   priv->wmm.ac_down_graded_vals[ac_val]);
                }
        }
 }
@@ -521,8 +524,8 @@ static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv)
        int i;
 
        for (i = 0; i < MAX_NUM_TID; ++i) {
-               dev_dbg(priv->adapter->dev,
-                       "info: ra_list: freeing buf for tid %d\n", i);
+               mwifiex_dbg(priv->adapter, INFO,
+                           "info: ra_list: freeing buf for tid %d\n", i);
                list_for_each_entry_safe(ra_list, tmp_node,
                                         &priv->wmm.tid_tbl_ptr[i].ra_list,
                                         list) {
@@ -694,14 +697,15 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
            ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) {
                if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)
-                       dev_dbg(adapter->dev,
-                               "TDLS setup packet for %pM. Don't block\n", ra);
+                       mwifiex_dbg(adapter, DATA,
+                                   "TDLS setup packet for %pM.\t"
+                                   "Don't block\n", ra);
                else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN))
                        tdls_status = mwifiex_get_tdls_link_status(priv, ra);
        }
 
        if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
-               dev_dbg(adapter->dev, "data: drop packet in disconnect\n");
+               mwifiex_dbg(adapter, DATA, "data: drop packet in disconnect\n");
                mwifiex_write_data_complete(adapter, skb, 0, -1);
                return;
        }
@@ -782,6 +786,7 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
 {
        u8 *curr = (u8 *) &resp->params.get_wmm_status;
        uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
+       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
        bool valid = true;
 
        struct mwifiex_ie_types_data *tlv_hdr;
@@ -789,8 +794,9 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
        struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
        struct mwifiex_wmm_ac_status *ac_status;
 
-       dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
-               resp_len);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
+                   resp_len);
 
        while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
                tlv_hdr = (struct mwifiex_ie_types_data *) curr;
@@ -804,12 +810,12 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
                        tlv_wmm_qstatus =
                                (struct mwifiex_ie_types_wmm_queue_status *)
                                tlv_hdr;
-                       dev_dbg(priv->adapter->dev,
-                               "info: CMD_RESP: WMM_GET_STATUS:"
-                               QSTATUS TLV: %d, %d, %d\n",
-                               tlv_wmm_qstatus->queue_index,
-                               tlv_wmm_qstatus->flow_required,
-                               tlv_wmm_qstatus->disabled);
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
+                                   "QSTATUS TLV: %d, %d, %d\n",
+                                   tlv_wmm_qstatus->queue_index,
+                                   tlv_wmm_qstatus->flow_required,
+                                   tlv_wmm_qstatus->disabled);
 
                        ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
                                                         queue_index];
@@ -832,11 +838,10 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
                        wmm_param_ie->vend_hdr.element_id =
                                                WLAN_EID_VENDOR_SPECIFIC;
 
-                       dev_dbg(priv->adapter->dev,
-                               "info: CMD_RESP: WMM_GET_STATUS:"
-                               " WMM Parameter Set Count: %d\n",
-                               wmm_param_ie->qos_info_bitmap &
-                               IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK);
+                       mwifiex_dbg(priv->adapter, CMD,
+                                   "info: CMD_RESP: WMM_GET_STATUS:\t"
+                                   "WMM Parameter Set Count: %d\n",
+                                   wmm_param_ie->qos_info_bitmap & mask);
 
                        memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
                               wmm_ie, wmm_param_ie,
@@ -884,9 +889,9 @@ mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
        if (!wmm_ie)
                return 0;
 
-       dev_dbg(priv->adapter->dev,
-               "info: WMM: process assoc req: bss->wmm_ie=%#x\n",
-               wmm_ie->vend_hdr.element_id);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: WMM: process assoc req: bss->wmm_ie=%#x\n",
+                   wmm_ie->vend_hdr.element_id);
 
        if ((priv->wmm_required ||
             (ht_cap && (priv->adapter->config_bands & BAND_GN ||
@@ -936,8 +941,8 @@ mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
         */
        ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1);
 
-       dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms,"
-                               " %d ms sent to FW\n", queue_delay, ret_val);
+       mwifiex_dbg(priv->adapter, DATA, "data: WMM: Pkt Delay: %d ms,\t"
+                   "%d ms sent to FW\n", queue_delay, ret_val);
 
        return ret_val;
 }
@@ -1091,14 +1096,15 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
        if (skb_queue_empty(&ptr->skb_head)) {
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
-               dev_dbg(adapter->dev, "data: nothing to send\n");
+               mwifiex_dbg(adapter, DATA, "data: nothing to send\n");
                return;
        }
 
        skb = skb_dequeue(&ptr->skb_head);
 
        tx_info = MWIFIEX_SKB_TXCB(skb);
-       dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);
+       mwifiex_dbg(adapter, DATA,
+                   "data: dequeuing the packet %p %p\n", ptr, skb);
 
        ptr->total_pkt_count--;
 
@@ -1214,7 +1220,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
 
        switch (ret) {
        case -EBUSY:
-               dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
+               mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
                spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
                if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
@@ -1233,7 +1239,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
        case -1:
                if (adapter->iface_type != MWIFIEX_PCIE)
                        adapter->data_sent = false;
-               dev_err(adapter->dev, "host_to_card failed: %#x\n", ret);
+               mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret);
                adapter->dbg.num_tx_host_to_card_failure++;
                mwifiex_write_data_complete(adapter, skb, 0, ret);
                break;
@@ -1272,7 +1278,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
 
        tid = mwifiex_get_tid(ptr);
 
-       dev_dbg(adapter->dev, "data: tid=%d\n", tid);
+       mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid);
 
        spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
        if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
index 477f86354dc5a7ff8a324717a16093cd9fc55f81..0881ba8535f4e11bec61d029dc58f29a7f0c4500 100644 (file)
@@ -143,7 +143,7 @@ static int psm;
 static char *essid;
 
 /* Default to encapsulation unless translation requested */
-static bool translate = 1;
+static bool translate = true;
 
 static int country = USA;
 
index 43db6976102f940c9e670f20996dd803467edb8a..71a825c750cfc5523fb28d40286cb22888b1bb26 100644 (file)
@@ -356,9 +356,9 @@ struct ndis_80211_pmkid {
 #define CAP_MODE_80211G                4
 #define CAP_MODE_MASK          7
 
-#define WORK_LINK_UP           (1<<0)
-#define WORK_LINK_DOWN         (1<<1)
-#define WORK_SET_MULTICAST_LIST        (1<<2)
+#define WORK_LINK_UP           0
+#define WORK_LINK_DOWN         1
+#define WORK_SET_MULTICAST_LIST        2
 
 #define RNDIS_WLAN_ALG_NONE    0
 #define RNDIS_WLAN_ALG_WEP     (1<<0)
index 5cf509d346e8f61f76ee00254c6cebab1f53ac2b..73067cac289c69c93560cb0801e181012b2d00ee 100644 (file)
@@ -100,7 +100,7 @@ config RTL8821AE
        select RTLWIFI_PCI
        select RTLBTCOEXIST
        ---help---
-       This is the driver for Realtek RTL8i821AE/RTL8812AE 802.11av PCIe
+       This is the driver for Realtek RTL8821AE/RTL8812AE 802.11ac PCIe
        wireless network adapters.
 
        If you choose to build it as a module, it will be called rtl8821ae
index cefe26991421b8e42c22ba6ef6beb4be0adb9d95..f2b9d11adc9eadca0d1cc833614c4c7cc69536c0 100644 (file)
@@ -1286,8 +1286,11 @@ static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec,
                                                    0x12, 0xe1, 0x90);
                        break;
                case 3:
-                       btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c,
-                                                   0x3, 0xf1, 0x90);
+                       /* This call breaks BT when wireless is active -
+                        * comment it out for now until a better fix is found:
+                        * btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c,
+                        *                          0x3, 0xf1, 0x90);
+                        */
                        break;
                case 4:
                        btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x10,
index 1893d01b9e789c1bca2f25f1e0fa5d067da99cfc..a62bf0a65c321bb73553c403c5233ccd30d1f8c7 100644 (file)
@@ -40,6 +40,7 @@ static struct country_code_to_enum_rd allCountries[] = {
        {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"},
        {COUNTRY_CODE_WORLD_WIDE_13, "EC"},
        {COUNTRY_CODE_TELEC_NETGEAR, "EC"},
+       {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"},
 };
 
 /*
@@ -124,6 +125,17 @@ static const struct ieee80211_regdomain rtl_regdom_14_60_64 = {
                      }
 };
 
+static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = {
+       .n_reg_rules = 4,
+       .alpha2 = "99",
+       .reg_rules = {
+                       RTL819x_2GHZ_CH01_11,
+                       RTL819x_2GHZ_CH12_13,
+                       RTL819x_5GHZ_5150_5350,
+                       RTL819x_5GHZ_5470_5850,
+               }
+};
+
 static const struct ieee80211_regdomain rtl_regdom_14 = {
        .n_reg_rules = 3,
        .alpha2 = "99",
@@ -348,6 +360,8 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select(
                return &rtl_regdom_14_60_64;
        case COUNTRY_CODE_GLOBAL_DOMAIN:
                return &rtl_regdom_14;
+       case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
+               return &rtl_regdom_12_13_5g_all;
        default:
                return &rtl_regdom_no_midband;
        }
@@ -384,6 +398,25 @@ static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode)
        return NULL;
 }
 
+static u8 channel_plan_to_country_code(u8 channelplan)
+{
+       switch (channelplan) {
+       case 0x20:
+       case 0x21:
+               return COUNTRY_CODE_WORLD_WIDE_13;
+       case 0x22:
+               return COUNTRY_CODE_IC;
+       case 0x32:
+               return COUNTRY_CODE_TELEC_NETGEAR;
+       case 0x41:
+               return COUNTRY_CODE_GLOBAL_DOMAIN;
+       case 0x7f:
+               return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL;
+       default:
+               return COUNTRY_CODE_MAX; /*Error*/
+       }
+}
+
 int rtl_regd_init(struct ieee80211_hw *hw,
                  void (*reg_notifier)(struct wiphy *wiphy,
                                       struct regulatory_request *request))
@@ -396,11 +429,12 @@ int rtl_regd_init(struct ieee80211_hw *hw,
                return -EINVAL;
 
        /* init country_code from efuse channel plan */
-       rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan;
+       rtlpriv->regd.country_code =
+               channel_plan_to_country_code(rtlpriv->efuse.channel_plan);
 
-       RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE,
-                "rtl: EEPROM regdomain: 0x%0x\n",
-                 rtlpriv->regd.country_code);
+       RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
+                "rtl: EEPROM regdomain: 0x%0x conuntry code: %d\n",
+                rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
 
        if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
                RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
index 3bbbaaa68530ef8678fbc0b65e5b91f81d50e301..f7f15bce35dd61309098b50d4ff08bee701dc5b3 100644 (file)
@@ -49,6 +49,7 @@ enum country_code_type_t {
        COUNTRY_CODE_GLOBAL_DOMAIN = 10,
        COUNTRY_CODE_WORLD_WIDE_13 = 11,
        COUNTRY_CODE_TELEC_NETGEAR = 12,
+       COUNTRY_CODE_WORLD_WIDE_13_5G_ALL = 13,
 
        /*add new channel plan above this line */
        COUNTRY_CODE_MAX
index 86ce5b1930e6d2824b66f7d5c95210c59fca6cb7..8ee83b093c0df4c2cca7e3368bdf46794980ec96 100644 (file)
@@ -1354,27 +1354,11 @@ void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
-static void rtl88ee_clear_interrupt(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 tmp;
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISR);
-       rtl_write_dword(rtlpriv, REG_HISR, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
-       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
-       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
-}
-
 void rtl88ee_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-       rtl88ee_clear_interrupt(hw);/*clear it here first*/
        rtl_write_dword(rtlpriv, REG_HIMR,
                        rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE,
@@ -1919,8 +1903,8 @@ static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw)
                 "dev_addr: %pM\n", rtlefuse->dev_addr);
        /*channel plan */
        rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN];
-       /* set channel paln to world wide 13 */
-       rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+       /* set channel plan from efuse */
+       rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
        /*tx power*/
        _rtl88ee_read_txpower_info_from_hwpg(hw,
                                             rtlefuse->autoload_failflag,
index ef28c8ea1e84601b34417a8f6760b2b824a235f8..02013df968a0abe09b89cd1c6ccc4ba4c70692b9 100644 (file)
@@ -23,7 +23,7 @@
  *
  *****************************************************************************/
 
-#include "pwrseqcmd.h"
+#include "../pwrseqcmd.h"
 #include "pwrseq.h"
 
 /* drivers should parse below arrays and do the corresponding actions */
index 79103347d96759c91cd67c1e49171d76381572a5..f2d9c6116e5c7f92f47f9845498bd52683d9975a 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef __RTL8723E_PWRSEQ_H__
 #define __RTL8723E_PWRSEQ_H__
 
-#include "pwrseqcmd.h"
+#include "../pwrseqcmd.h"
 /* Check document WM-20110607-Paul-RTL8188EE_Power_Architecture-R02.vsd
  *     There are 6 HW Power States:
  *     0: POFF--Power Off
index d310d55d800efd584f9dd9a6d8e143539c0c777c..189859617db803e4440cff48568a3165790f4a45 100644 (file)
@@ -889,7 +889,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
        rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version));
        rtl92c_init_beacon_parameters(hw, rtlhal->version);
        rtl92c_init_ampdu_aggregation(hw);
-       rtl92c_init_beacon_max_error(hw, true);
+       rtl92c_init_beacon_max_error(hw);
        return err;
 }
 
@@ -1323,7 +1323,6 @@ static int _rtl92cu_set_media_status(struct ieee80211_hw *hw,
        enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
 
        bt_msr &= 0xfc;
-       rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
        if (type == NL80211_IFTYPE_UNSPECIFIED || type ==
            NL80211_IFTYPE_STATION) {
                _rtl92cu_stop_tx_beacon(hw);
index adb810794eef71e27080cd9590a07911eba5123b..f3db6bc8596a3143436eb7db2710d825d7dee8d6 100644 (file)
@@ -613,7 +613,7 @@ void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
        rtl_write_word(rtlpriv, 0x4CA, 0x0708);
 }
 
-void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
index bf53652e4eddb3428c5e80850c0a3aa59e4346f3..58548e8f2c41b64276ec1c696b6bf03fd79fc4b9 100644 (file)
@@ -66,7 +66,7 @@ void rtl92c_init_edca_param(struct ieee80211_hw *hw,
 
 void rtl92c_init_edca(struct ieee80211_hw *hw);
 void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw);
-void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode);
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw);
 void rtl92c_init_rdg_setting(struct ieee80211_hw *hw);
 void rtl92c_init_retry_function(struct ieee80211_hw *hw);
 
index da0a6125f314b7c582eefb5ea297fd2efd593ca0..5f14308e8eb35e9914724ce8b610e14497dccef7 100644 (file)
@@ -1584,28 +1584,11 @@ void rtl92ee_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
-static void rtl92ee_clear_interrupt(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 tmp;
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISR);
-       rtl_write_dword(rtlpriv, REG_HISR, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
-       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
-       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
-}
-
 void rtl92ee_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-       rtl92ee_clear_interrupt(hw);/*clear it here first*/
-
        rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
        rtlpci->irq_enabled = true;
@@ -2194,8 +2177,8 @@ static void _rtl92ee_read_adapter_info(struct ieee80211_hw *hw)
                 "dev_addr: %pM\n", rtlefuse->dev_addr);
        /*channel plan */
        rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
-       /* set channel paln to world wide 13 */
-       rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+       /* set channel plan from efuse */
+       rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
        /*tx power*/
        _rtl92ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag,
                                             hwinfo);
index 67bb47d77b68c5d45bd6bb6dc0f0721c2461fa2c..a4b7eac6856f2cac9937807e61c05d94cf22a689 100644 (file)
@@ -1258,18 +1258,6 @@ void rtl8723e_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
-static void rtl8723e_clear_interrupt(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 tmp;
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISR);
-       rtl_write_dword(rtlpriv, REG_HISR, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
-       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
-}
-
 void rtl8723e_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1284,7 +1272,6 @@ void rtl8723e_disable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-       rtl8723e_clear_interrupt(hw);/*clear it here first*/
        rtl_write_dword(rtlpriv, 0x3a8, IMR8190_DISABLED);
        rtl_write_dword(rtlpriv, 0x3ac, IMR8190_DISABLED);
        rtlpci->irq_enabled = false;
index b681af3c7a355d66fb411c71dcdcbba5bb8dfc01..c983d2fe147f2bf1da4923f2ddc8f2bbbfcd90de 100644 (file)
@@ -1634,28 +1634,11 @@ void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
-static void rtl8723be_clear_interrupt(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 tmp;
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISR);
-       rtl_write_dword(rtlpriv, REG_HISR, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
-       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
-       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
-}
-
 void rtl8723be_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-       rtl8723be_clear_interrupt(hw);/*clear it here first*/
-
        rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
        rtlpci->irq_enabled = true;
@@ -2139,8 +2122,8 @@ static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw,
        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
                 "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
 
-       /* set channel plan to world wide 13 */
-       rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+       /* set channel plan from efuse */
+       rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
 
        if (rtlhal->oem_id == RT_CID_DEFAULT) {
                /* Does this one have a Toshiba SMID from group 1? */
index 8704eee9f3a495108e93135d6e306a090c322bc7..3236d44b459df69efd4f2b363f4b651e478a10a4 100644 (file)
@@ -2253,31 +2253,11 @@ void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
-static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 tmp;
-       tmp = rtl_read_dword(rtlpriv, REG_HISR);
-       /*printk("clear interrupt first:\n");
-       printk("0x%x = 0x%08x\n",REG_HISR, tmp);*/
-       rtl_write_dword(rtlpriv, REG_HISR, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
-       /*printk("0x%x = 0x%08x\n",REG_HISRE, tmp);*/
-       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
-
-       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
-       /*printk("0x%x = 0x%08x\n",REG_HSISR, tmp);*/
-       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
-}
-
 void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-       rtl8821ae_clear_interrupt(hw);/*clear it here first*/
-
        rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
        rtlpci->irq_enabled = true;
@@ -3232,8 +3212,8 @@ static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_
        if (rtlefuse->eeprom_channelplan == 0xff)
                rtlefuse->eeprom_channelplan = 0x7F;
 
-       /* set channel paln to world wide 13 */
-       /* rtlefuse->channel_plan = (u8)rtlefuse->eeprom_channelplan; */
+       /* set channel plan from efuse */
+       rtlefuse->channel_plan = rtlefuse->eeprom_channelplan;
 
        /*parse xtal*/
        rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8821AE];
index e34f906647d39dce39985d1cfe836f42b689c556..2ff4a9961e1d5166741f98f80651a516d6ef8eb5 100644 (file)
@@ -305,6 +305,15 @@ int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
 
 extern void bcma_driver_unregister(struct bcma_driver *drv);
 
+/* module_bcma_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_bcma_driver(__bcma_driver) \
+       module_driver(__bcma_driver, bcma_driver_register, \
+                       bcma_driver_unregister)
+
 /* Set a fallback SPROM.
  * See kdoc at the function definition for complete documentation. */
 extern int bcma_arch_register_fallback_sprom(