]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
wcn36xx: Replace with latest development version
authorBjorn Andersson <bjorn.andersson@linaro.org>
Tue, 7 Jun 2016 04:59:29 +0000 (21:59 -0700)
committerNicolas Dechesne <nicolas.dechesne@linaro.org>
Tue, 21 Jun 2016 08:02:22 +0000 (11:02 +0300)
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
drivers/net/wireless/ath/wcn36xx/Kconfig
drivers/net/wireless/ath/wcn36xx/Makefile
drivers/net/wireless/ath/wcn36xx/dxe.c
drivers/net/wireless/ath/wcn36xx/dxe.h
drivers/net/wireless/ath/wcn36xx/hal.h
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wcn36xx/smd.h
drivers/net/wireless/ath/wcn36xx/txrx.c
drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c [deleted file]
drivers/net/wireless/ath/wcn36xx/wcn36xx.h

index 591ebaea826564bf339f82b8152394dca022b5e8..394fe5b77c904b92fcd494e86eaad7863a49fe72 100644 (file)
@@ -1,6 +1,6 @@
 config WCN36XX
        tristate "Qualcomm Atheros WCN3660/3680 support"
-       depends on MAC80211 && HAS_DMA
+       depends on MAC80211 && HAS_DMA && QCOM_SMD
        ---help---
          This module adds support for wireless adapters based on
          Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
index fdf89a53ce75582ce2b3ffb770146e292d26e477..50c43b4382bacd91c9ff8380a1af0eaaafea5ba1 100644 (file)
@@ -1,9 +1,7 @@
-obj-$(CONFIG_WCN36XX) := wcn36xx.o wcn36xx-platform.o
+obj-$(CONFIG_WCN36XX) := wcn36xx.o
 wcn36xx-y +=   main.o \
                dxe.o \
                txrx.o \
                smd.o \
                pmc.o \
                debug.o
-
-wcn36xx-platform-y     += wcn36xx-msm.o
index af0e515f634da99f002c07c859a9822b5818a34f..87dfdaf9044cdf8b41aba6b8345e9d2f9dd325a6 100644 (file)
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/interrupt.h>
+#include <linux/soc/qcom/smem_state.h>
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -35,26 +36,27 @@ void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
        return ch->head_blk_ctl->bd_cpu_addr;
 }
 
+static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data)
+{
+       wcn36xx_dbg(WCN36XX_DBG_DXE,
+                   "wcn36xx_ccu_write_register: addr=%x, data=%x\n",
+                   addr, data);
+
+       writel(data, wcn->ccu_base + addr);
+}
+
 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
 {
        wcn36xx_dbg(WCN36XX_DBG_DXE,
                    "wcn36xx_dxe_write_register: addr=%x, data=%x\n",
                    addr, data);
 
-       writel(data, wcn->mmio + addr);
+       writel(data, wcn->dxe_base + addr);
 }
 
-#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data)                \
-do {                                                                    \
-       if (wcn->chip_version != WCN36XX_CHIP_3660)                      \
-               wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
-       else                                                             \
-               wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
-} while (0)                                                             \
-
 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
 {
-       *data = readl(wcn->mmio + addr);
+       *data = readl(wcn->dxe_base + addr);
 
        wcn36xx_dbg(WCN36XX_DBG_DXE,
                    "wcn36xx_dxe_read_register: addr=%x, data=%x\n",
@@ -150,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
                goto out_err;
 
        /* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-       ret = wcn->ctrl_ops->smsm_change_state(
-               WCN36XX_SMSM_WLAN_TX_ENABLE,
-               WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+       ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+                                         WCN36XX_SMSM_WLAN_TX_ENABLE |
+                                         WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+                                         WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+       if (ret)
+               goto out_err;
 
        return 0;
 
@@ -677,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
         * notify chip about new frame through SMSM bus.
         */
        if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-               wcn->ctrl_ops->smsm_change_state(
-                                 0,
-                                 WCN36XX_SMSM_WLAN_TX_ENABLE);
+               qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+                                           WCN36XX_SMSM_WLAN_TX_ENABLE,
+                                           WCN36XX_SMSM_WLAN_TX_ENABLE);
        } else {
                /* indicate End Of Packet and generate interrupt on descriptor
                 * done.
@@ -701,9 +706,13 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
        reg_data = WCN36XX_DXE_REG_RESET;
        wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
 
-       /* Setting interrupt path */
-       reg_data = WCN36XX_DXE_CCU_INT;
-       wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
+       /* Select channels for rx avail and xfer done interrupts... */
+       reg_data = (WCN36XX_DXE_INT_CH3_MASK | WCN36XX_DXE_INT_CH1_MASK) << 16 |
+                   WCN36XX_DXE_INT_CH0_MASK | WCN36XX_DXE_INT_CH4_MASK;
+       if (wcn->is_pronto)
+               wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_PRONTO, reg_data);
+       else
+               wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_RIVA, reg_data);
 
        /***************************************/
        /* Init descriptors for TX LOW channel */
index 3eca4f9594f2a3a3c638996fd13daae66e473283..c012e807753b763112a1be05b046b71f2d51087f 100644 (file)
@@ -28,11 +28,10 @@ H2H_TEST_RX_TX = DMA2
 */
 
 /* DXE registers */
-#define WCN36XX_DXE_MEM_REG                    0x202000
+#define WCN36XX_DXE_MEM_REG                    0
 
-#define WCN36XX_DXE_CCU_INT                    0xA0011
-#define WCN36XX_DXE_REG_CCU_INT_3660           0x200b10
-#define WCN36XX_DXE_REG_CCU_INT_3680           0x2050dc
+#define WCN36XX_CCU_DXE_INT_SELECT_RIVA                0x310
+#define WCN36XX_CCU_DXE_INT_SELECT_PRONTO      0x10dc
 
 /* TODO This must calculated properly but not hardcoded */
 #define WCN36XX_DXE_CTRL_TX_L                  0x328a44
index dbf1769a969920875e198436214eff8906c0a59d..4f87ef1e1eb866808ecc0b071b28d7bd4bbaeff1 100644 (file)
@@ -51,7 +51,7 @@
 #define WCN36XX_HAL_STA_INVALID_IDX 0xFF
 #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF
 
-/* Default Beacon template size. */
+/* Default Beacon template size */
 #define BEACON_TEMPLATE_SIZE 0x180
 
 /* Minimum PVM size that the FW expects. See comment in smd.c for details. */
@@ -350,8 +350,6 @@ enum wcn36xx_hal_host_msg_type {
 
        WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
 
-       WCN36XX_HAL_PRINT_REG_INFO_IND = 259,
-
        WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
 };
 
@@ -2889,11 +2887,13 @@ struct update_beacon_rsp_msg {
 struct wcn36xx_hal_send_beacon_req_msg {
        struct wcn36xx_hal_msg_header header;
 
-       /* length of the template + sizeof(beacon_length) */
-       u32 template_length;
+       /* length of the template + 6. Only qcom knows why */
+       u32 beacon_length6;
 
-       /* Beacon data. */
+       /* length of the template. */
        u32 beacon_length;
+
+       /* Beacon data. */
        u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)];
 
        u8 bssid[ETH_ALEN];
@@ -4123,7 +4123,7 @@ struct wcn36xx_hal_update_scan_params_req {
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
-struct update_scan_params_req_ex {
+struct wcn36xx_hal_update_scan_params_req_ex {
 
        struct wcn36xx_hal_msg_header header;
 
@@ -4151,7 +4151,7 @@ struct update_scan_params_req_ex {
 
        /* Cb State */
        enum phy_chan_bond_state state;
-};
+} __packed;
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
index 5b9c923779248b36fa37fbb5132edebebb8dc5de..abc2e4efcf87c40f91106ef42af56374c4fbb730 100644 (file)
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/soc/qcom/smd.h>
+#include <linux/soc/qcom/smem_state.h>
+#include <linux/soc/qcom/wcnss_ctrl.h>
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -27,14 +32,14 @@ module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
 MODULE_PARM_DESC(debug_mask, "Debugging mask");
 
 #define CHAN2G(_freq, _idx) { \
-       .band = IEEE80211_BAND_2GHZ, \
+       .band = NL80211_BAND_2GHZ, \
        .center_freq = (_freq), \
        .hw_value = (_idx), \
        .max_power = 25, \
 }
 
 #define CHAN5G(_freq, _idx) { \
-       .band = IEEE80211_BAND_5GHZ, \
+       .band = NL80211_BAND_5GHZ, \
        .center_freq = (_freq), \
        .hw_value = (_idx), \
        .max_power = 25, \
@@ -314,8 +319,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
                        wcn36xx_feat_caps_info(wcn);
        }
 
-       wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
-
        /* DMA channel initialization */
        ret = wcn36xx_dxe_init(wcn);
        if (ret) {
@@ -382,8 +385,6 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
        return 0;
 }
 
-#define WCN36XX_SUPPORTED_FILTERS (FIF_ALLMULTI)
-
 static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
                                     unsigned int changed,
                                     unsigned int *total, u64 multicast)
@@ -395,7 +396,7 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
 
        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
 
-       *total &= WCN36XX_SUPPORTED_FILTERS;
+       *total &= FIF_ALLMULTI;
 
        fp = (void *)(unsigned long)multicast;
        list_for_each_entry(tmp, &wcn->vif_list, list) {
@@ -567,27 +568,61 @@ out:
        return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
-                                 struct ieee80211_vif *vif,
-                                 const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-       struct wcn36xx *wcn = hw->priv;
+       struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+       struct cfg80211_scan_request *req = wcn->scan_req;
+       u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+       int i;
+
+       wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels);
+
+       for (i = 0; i < req->n_channels; i++)
+               channels[i] = req->channels[i]->hw_value;
+
+       wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
        wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-       wcn36xx_smd_start_scan(wcn);
+       for (i = 0; i < req->n_channels; i++) {
+               wcn->scan_freq = req->channels[i]->center_freq;
+               wcn->scan_band = req->channels[i]->band;
+
+               wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+               msleep(30);
+               wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+               wcn->scan_freq = 0;
+       }
+       wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+       ieee80211_scan_completed(wcn->hw, false);
+
+       mutex_lock(&wcn->scan_lock);
+       wcn->scan_req = NULL;
+       mutex_unlock(&wcn->scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-                                    struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+                          struct ieee80211_vif *vif,
+                          struct ieee80211_scan_request *hw_req)
 {
        struct wcn36xx *wcn = hw->priv;
 
-       wcn36xx_smd_end_scan(wcn);
-       wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+       mutex_lock(&wcn->scan_lock);
+       if (wcn->scan_req) {
+               mutex_unlock(&wcn->scan_lock);
+               return -EBUSY;
+       }
+       wcn->scan_req = &hw_req->req;
+       mutex_unlock(&wcn->scan_lock);
+
+       schedule_work(&wcn->scan_work);
+
+       return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
-                                        enum ieee80211_band band)
+                                        enum nl80211_band band)
 {
        int i, size;
        u16 *rates_table;
@@ -600,7 +635,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
 
        size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
        rates_table = sta_priv->supported_rates.dsss_rates;
-       if (band == IEEE80211_BAND_2GHZ) {
+       if (band == NL80211_BAND_2GHZ) {
                for (i = 0; i < size; i++) {
                        if (rates & 0x01) {
                                rates_table[i] = wcn_2ghz_rates[i].hw_value;
@@ -994,8 +1029,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
        .configure_filter       = wcn36xx_configure_filter,
        .tx                     = wcn36xx_tx,
        .set_key                = wcn36xx_set_key,
-       .sw_scan_start          = wcn36xx_sw_scan_start,
-       .sw_scan_complete       = wcn36xx_sw_scan_complete,
+       .hw_scan                = wcn36xx_hw_scan,
        .bss_info_changed       = wcn36xx_bss_info_changed,
        .set_rts_threshold      = wcn36xx_set_rts_threshold,
        .sta_add                = wcn36xx_sta_add,
@@ -1020,27 +1054,24 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
        ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
        ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
        ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
-
-       /* 3620 powersaving currently unstable */
-       if (wcn->chip_version == WCN36XX_CHIP_3620)
-               __clear_bit(IEEE80211_HW_SUPPORTS_PS, wcn->hw->flags);
+       ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
        wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_ADHOC) |
                BIT(NL80211_IFTYPE_MESH_POINT);
 
-       wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz;
-       wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz;
+       wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
+       wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
+
+       wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+       wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
 
        wcn->hw->wiphy->cipher_suites = cipher_suites;
        wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
        wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
 
-       /* TODO: Figure out why this is necessary */
-       wcn->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
 #ifdef CONFIG_PM
        wcn->hw->wiphy->wowlan = &wowlan_support;
 #endif
@@ -1060,47 +1091,91 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
                                          struct platform_device *pdev)
 {
-       u32 mmio[2];
+       struct device_node *mmio_node;
+       struct resource *res;
+       int index;
        int ret;
 
        /* Set TX IRQ */
-       wcn->tx_irq = irq_of_parse_and_map(pdev->dev.parent->of_node, 0);
-       if (!wcn->tx_irq) {
+       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
+       if (!res) {
                wcn36xx_err("failed to get tx_irq\n");
                return -ENOENT;
        }
+       wcn->tx_irq = res->start;
 
        /* Set RX IRQ */
-       wcn->rx_irq = irq_of_parse_and_map(pdev->dev.parent->of_node, 1);
-       if (!wcn->rx_irq) {
+       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
+       if (!res) {
                wcn36xx_err("failed to get rx_irq\n");
                return -ENOENT;
        }
+       wcn->rx_irq = res->start;
 
-       /* Map the memory */
-       ret = of_property_read_u32_array(pdev->dev.parent->of_node, "qcom,wcnss-mmio", mmio, 2);
-       if (ret) {
-               wcn36xx_err("failed to get qcom,wcnss-mmio\n");
+       /* Acquire SMSM tx enable handle */
+       wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
+                       "tx-enable", &wcn->tx_enable_state_bit);
+       if (IS_ERR(wcn->tx_enable_state)) {
+               wcn36xx_err("failed to get tx-enable state\n");
                return -ENOENT;
        }
 
-       wcn->mmio = ioremap(mmio[0], mmio[1]);
-       if (!wcn->mmio) {
-               wcn36xx_err("failed to map io memory\n");
-               return -ENOMEM;
+       /* Acquire SMSM tx rings empty handle */
+       wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
+                       "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
+       if (IS_ERR(wcn->tx_rings_empty_state)) {
+               wcn36xx_err("failed to get tx-rings-empty state\n");
+               return -ENOENT;
+       }
+
+       mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
+       if (!mmio_node) {
+               wcn36xx_err("failed to acquire qcom,mmio reference\n");
+               return -EINVAL;
+       }
+
+       wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
+
+       /* Map the CCU memory */
+       index = of_property_match_string(mmio_node, "reg-names", "ccu");
+       wcn->ccu_base = of_iomap(mmio_node, index);
+       if (!wcn->ccu_base) {
+               wcn36xx_err("failed to map ccu memory\n");
+               ret = -ENOMEM;
+               goto put_mmio_node;
+       }
+
+       /* Map the DXE memory */
+       index = of_property_match_string(mmio_node, "reg-names", "dxe");
+       wcn->dxe_base = of_iomap(mmio_node, index);
+       if (!wcn->dxe_base) {
+               wcn36xx_err("failed to map dxe memory\n");
+               ret = -ENOMEM;
+               goto unmap_ccu;
        }
+
+       of_node_put(mmio_node);
        return 0;
+
+unmap_ccu:
+       iounmap(wcn->ccu_base);
+put_mmio_node:
+       of_node_put(mmio_node);
+       return ret;
 }
 
 static int wcn36xx_probe(struct platform_device *pdev)
 {
        struct ieee80211_hw *hw;
        struct wcn36xx *wcn;
+       void *wcnss;
        int ret;
-       u8 addr[ETH_ALEN];
+       const u8 *addr;
 
        wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
 
+       wcnss = dev_get_drvdata(pdev->dev.parent);
+
        hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
        if (!hw) {
                wcn36xx_err("failed to alloc hw\n");
@@ -1111,25 +1186,26 @@ static int wcn36xx_probe(struct platform_device *pdev)
        wcn = hw->priv;
        wcn->hw = hw;
        wcn->dev = &pdev->dev;
-       wcn->dev->dma_mask = kzalloc(sizeof(*wcn->dev->dma_mask), GFP_KERNEL);
-       if (!wcn->dev->dma_mask) {
-               ret = -ENOMEM;
-               goto dma_mask_err;
-       }
-       dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
-       wcn->wcn36xx_data = pdev->dev.platform_data;
-       wcn->ctrl_ops = &wcn->wcn36xx_data->ctrl_ops;
-       wcn->wcn36xx_data->wcn = wcn;
-       if (!wcn->ctrl_ops->get_chip_type) {
-               dev_err(&pdev->dev, "Missing ops->get_chip_type\n");
-               ret = -EINVAL;
+       mutex_init(&wcn->hal_mutex);
+       mutex_init(&wcn->scan_lock);
+
+       INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
+
+       wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process);
+       if (IS_ERR(wcn->smd_channel)) {
+               wcn36xx_err("failed to open WLAN_CTRL channel\n");
+               ret = PTR_ERR(wcn->smd_channel);
                goto out_wq;
        }
-       wcn->chip_version = wcn->ctrl_ops->get_chip_type(wcn);
 
-       mutex_init(&wcn->hal_mutex);
+       qcom_smd_set_drvdata(wcn->smd_channel, hw);
 
-       if (!wcn->ctrl_ops->get_hw_mac(wcn, addr)) {
+       addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
+       if (addr && ret != ETH_ALEN) {
+               wcn36xx_err("invalid local-mac-address\n");
+               ret = -EINVAL;
+               goto out_wq;
+       } else if (addr) {
                wcn36xx_info("mac address: %pM\n", addr);
                SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
        }
@@ -1146,14 +1222,14 @@ static int wcn36xx_probe(struct platform_device *pdev)
        return 0;
 
 out_unmap:
-       iounmap(wcn->mmio);
+       iounmap(wcn->ccu_base);
+       iounmap(wcn->dxe_base);
 out_wq:
-       kfree(wcn->dev->dma_mask);
-dma_mask_err:
        ieee80211_free_hw(hw);
 out_err:
        return ret;
 }
+
 static int wcn36xx_remove(struct platform_device *pdev)
 {
        struct ieee80211_hw *hw = platform_get_drvdata(pdev);
@@ -1164,41 +1240,33 @@ static int wcn36xx_remove(struct platform_device *pdev)
        mutex_destroy(&wcn->hal_mutex);
 
        ieee80211_unregister_hw(hw);
-       iounmap(wcn->mmio);
+
+       qcom_smem_state_put(wcn->tx_enable_state);
+       qcom_smem_state_put(wcn->tx_rings_empty_state);
+
+       iounmap(wcn->dxe_base);
+       iounmap(wcn->ccu_base);
        ieee80211_free_hw(hw);
 
        return 0;
 }
-static const struct platform_device_id wcn36xx_platform_id_table[] = {
-       {
-               .name = "wcn36xx",
-               .driver_data = 0
-       },
+
+static const struct of_device_id wcn36xx_of_match[] = {
+       { .compatible = "qcom,wcnss-wlan" },
        {}
 };
-MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
+MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
 
 static struct platform_driver wcn36xx_driver = {
        .probe      = wcn36xx_probe,
        .remove     = wcn36xx_remove,
        .driver         = {
                .name   = "wcn36xx",
+               .of_match_table = wcn36xx_of_match,
        },
-       .id_table    = wcn36xx_platform_id_table,
 };
 
-static int __init wcn36xx_init(void)
-{
-       platform_driver_register(&wcn36xx_driver);
-       return 0;
-}
-module_init(wcn36xx_init);
-
-static void __exit wcn36xx_exit(void)
-{
-       platform_driver_unregister(&wcn36xx_driver);
-}
-module_exit(wcn36xx_exit);
+module_platform_driver(wcn36xx_driver);
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
index 61754967e2effc5429515ffc35ca25ba4f5cde01..87a62eb6228cab3352e79f166e5824e5f478426e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
 #include <linux/bitops.h>
+#include <linux/soc/qcom/smd.h>
 #include "smd.h"
 
 struct wcn36xx_cfg_val {
@@ -104,11 +105,11 @@ static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
                struct ieee80211_sta *sta,
                struct wcn36xx_hal_config_bss_params *bss_params)
 {
-       if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn))
+       if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
                bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
        else if (sta && sta->ht_cap.ht_supported)
                bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
-       else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f))
+       else if (sta && (sta->supp_rates[NL80211_BAND_2GHZ] & 0x7f))
                bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
        else
                bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
@@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 
        init_completion(&wcn->hal_rsp_compl);
        start = jiffies;
-       ret = wcn->ctrl_ops->tx(wcn, wcn->hal_buf, len);
+       ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
        if (ret) {
                wcn36xx_err("HAL TX failed\n");
                goto out;
@@ -521,7 +522,7 @@ out:
        return ret;
 }
 
-int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
+int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
 {
        struct wcn36xx_hal_start_scan_req_msg msg_body;
        int ret = 0;
@@ -529,7 +530,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
        mutex_lock(&wcn->hal_mutex);
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
 
-       msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
+       msg_body.scan_channel = scan_channel;
 
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -551,7 +552,7 @@ out:
        return ret;
 }
 
-int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
+int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
 {
        struct wcn36xx_hal_end_scan_req_msg msg_body;
        int ret = 0;
@@ -559,7 +560,7 @@ int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
        mutex_lock(&wcn->hal_mutex);
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
 
-       msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
+       msg_body.scan_channel = scan_channel;
 
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -674,22 +675,25 @@ static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
        return 0;
 }
 
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
+                                  u8 *channels, size_t channel_count)
 {
-       struct wcn36xx_hal_update_scan_params_req msg_body;
+       struct wcn36xx_hal_update_scan_params_req_ex msg_body;
        int ret = 0;
 
        mutex_lock(&wcn->hal_mutex);
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
 
-       msg_body.dot11d_enabled = 0;
-       msg_body.dot11d_resolved = 0;
-       msg_body.channel_count = 26;
+       msg_body.dot11d_enabled = false;
+       msg_body.dot11d_resolved = true;
+
+       msg_body.channel_count = channel_count;
+       memcpy(msg_body.channels, channels, channel_count);
        msg_body.active_min_ch_time = 60;
        msg_body.active_max_ch_time = 120;
        msg_body.passive_min_ch_time = 60;
        msg_body.passive_max_ch_time = 110;
-       msg_body.state = 0;
+       msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
 
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -1388,7 +1392,6 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
 {
        struct wcn36xx_hal_send_beacon_req_msg msg_body;
        int ret = 0, pad, pvm_len;
-       u32 beacon_length;
 
        mutex_lock(&wcn->hal_mutex);
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
@@ -1400,16 +1403,16 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
        if (vif->type == NL80211_IFTYPE_MESH_POINT)
                pad = 0;
 
-       beacon_length = skb_beacon->len + pad;
-       msg_body.template_length = beacon_length + sizeof(beacon_length);
+       msg_body.beacon_length = skb_beacon->len + pad;
+       /* TODO need to find out why + 6 is needed */
+       msg_body.beacon_length6 = msg_body.beacon_length + 6;
 
-       if (msg_body.template_length > BEACON_TEMPLATE_SIZE) {
+       if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
                wcn36xx_err("Beacon is to big: beacon size=%d\n",
-                             msg_body.template_length);
+                             msg_body.beacon_length);
                ret = -ENOMEM;
                goto out;
        }
-       msg_body.beacon_length = beacon_length;
        memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
        memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
 
@@ -2178,13 +2181,18 @@ out:
        return ret;
 }
 
-static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
+int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
+                           const void *buf, size_t len)
 {
-       struct wcn36xx_hal_msg_header *msg_header = buf;
+       struct wcn36xx_hal_msg_header msg_header;
+       struct ieee80211_hw *hw = qcom_smd_get_drvdata(channel);
+       struct wcn36xx *wcn = hw->priv;
        struct wcn36xx_hal_ind_msg *msg_ind;
        wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
 
-       switch (msg_header->msg_type) {
+       memcpy_fromio(&msg_header, buf, sizeof(struct wcn36xx_hal_msg_header));
+
+       switch (msg_header.msg_type) {
        case WCN36XX_HAL_START_RSP:
        case WCN36XX_HAL_CONFIG_STA_RSP:
        case WCN36XX_HAL_CONFIG_BSS_RSP:
@@ -2220,44 +2228,42 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
        case WCN36XX_HAL_CH_SWITCH_RSP:
        case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
        case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
-               memcpy(wcn->hal_buf, buf, len);
+               memcpy_fromio(wcn->hal_buf, buf, len);
                wcn->hal_rsp_len = len;
                complete(&wcn->hal_rsp_compl);
                break;
 
-       case WCN36XX_HAL_DEL_BA_IND:
-       case WCN36XX_HAL_PRINT_REG_INFO_IND:
        case WCN36XX_HAL_COEX_IND:
        case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
        case WCN36XX_HAL_OTA_TX_COMPL_IND:
        case WCN36XX_HAL_MISSED_BEACON_IND:
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
-               msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               if (!msg_ind)
-                       goto nomem;
-               msg_ind->msg_len = len;
-               msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
-               if (!msg_ind->msg) {
-                       kfree(msg_ind);
-nomem:
+               msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
+               if (!msg_ind) {
                        /*
                         * FIXME: Do something smarter then just
                         * printing an error.
                         */
                        wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
-                                   msg_header->msg_type);
+                                   msg_header.msg_type);
                        break;
                }
-               mutex_lock(&wcn->hal_ind_mutex);
+
+               msg_ind->msg_len = len;
+               memcpy_fromio(msg_ind->msg, buf, len);
+
+               spin_lock(&wcn->hal_ind_lock);
                list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
                queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-               mutex_unlock(&wcn->hal_ind_mutex);
+               spin_unlock(&wcn->hal_ind_lock);
                wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
                break;
        default:
                wcn36xx_err("SMD_EVENT (%d) not supported\n",
-                             msg_header->msg_type);
+                             msg_header.msg_type);
        }
+
+       return 0;
 }
 static void wcn36xx_ind_smd_work(struct work_struct *work)
 {
@@ -2265,8 +2271,9 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
                container_of(work, struct wcn36xx, hal_ind_work);
        struct wcn36xx_hal_msg_header *msg_header;
        struct wcn36xx_hal_ind_msg *hal_ind_msg;
+       unsigned long flags;
 
-       mutex_lock(&wcn->hal_ind_mutex);
+       spin_lock_irqsave(&wcn->hal_ind_lock, flags);
 
        hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
                                       struct wcn36xx_hal_ind_msg,
@@ -2275,8 +2282,6 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
        msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
 
        switch (msg_header->msg_type) {
-       case WCN36XX_HAL_DEL_BA_IND:
-       case WCN36XX_HAL_PRINT_REG_INFO_IND:
        case WCN36XX_HAL_COEX_IND:
        case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
                break;
@@ -2300,9 +2305,8 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
                              msg_header->msg_type);
        }
        list_del(wcn->hal_ind_queue.next);
-       kfree(hal_ind_msg->msg);
+       spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
        kfree(hal_ind_msg);
-       mutex_unlock(&wcn->hal_ind_mutex);
 }
 int wcn36xx_smd_open(struct wcn36xx *wcn)
 {
@@ -2315,25 +2319,15 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
        }
        INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
        INIT_LIST_HEAD(&wcn->hal_ind_queue);
-       mutex_init(&wcn->hal_ind_mutex);
-
-       ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
-       if (ret) {
-               wcn36xx_err("failed to open control channel\n");
-               goto free_wq;
-       }
+       spin_lock_init(&wcn->hal_ind_lock);
 
-       return ret;
+       return 0;
 
-free_wq:
-       destroy_workqueue(wcn->hal_ind_wq);
 out:
        return ret;
 }
 
 void wcn36xx_smd_close(struct wcn36xx *wcn)
 {
-       wcn->ctrl_ops->close(wcn);
        destroy_workqueue(wcn->hal_ind_wq);
-       mutex_destroy(&wcn->hal_ind_mutex);
 }
index d93e3fd73831c98b67ddf32c1cf436d32a34d20e..8892ccd67b144903ae25cde3287e79f951e5a8c6 100644 (file)
@@ -46,11 +46,12 @@ struct wcn36xx_fw_msg_status_rsp {
 
 struct wcn36xx_hal_ind_msg {
        struct list_head list;
-       u8 *msg;
        size_t msg_len;
+       u8 msg[];
 };
 
 struct wcn36xx;
+struct qcom_smd_channel;
 
 int wcn36xx_smd_open(struct wcn36xx *wcn);
 void wcn36xx_smd_close(struct wcn36xx *wcn);
@@ -59,11 +60,11 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn);
 int wcn36xx_smd_start(struct wcn36xx *wcn);
 int wcn36xx_smd_stop(struct wcn36xx *wcn);
 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode);
-int wcn36xx_smd_start_scan(struct wcn36xx *wcn);
-int wcn36xx_smd_end_scan(struct wcn36xx *wcn);
+int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel);
+int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel);
 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
                            enum wcn36xx_hal_sys_mode mode);
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn);
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count);
 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif);
 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr);
 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index);
@@ -127,6 +128,10 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
 
 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
+
+int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel,
+                           const void *buf, size_t len);
+
 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
                            struct ieee80211_vif *vif,
                            struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp);
index 37f13410e6339c38a656be6a67aacd54418e1194..8c387a0a3c091c474e8f7dd948dc31b9060c0813 100644 (file)
@@ -45,9 +45,20 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
        skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
        skb_pull(skb, bd->pdu.mpdu_header_off);
 
+       hdr = (struct ieee80211_hdr *) skb->data;
+       fc = __le16_to_cpu(hdr->frame_control);
+       sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
+
+       /* When scanning associate beacons to this */
+       if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) {
+               status.freq = wcn->scan_freq;
+               status.band = wcn->scan_band;
+       } else {
+               status.freq = WCN36XX_CENTER_FREQ(wcn);
+               status.band = WCN36XX_BAND(wcn);
+       }
+
        status.mactime = 10;
-       status.freq = WCN36XX_CENTER_FREQ(wcn);
-       status.band = WCN36XX_BAND(wcn);
        status.signal = -get_rssi0(bd);
        status.antenna = 1;
        status.rate_idx = 1;
@@ -57,14 +68,10 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
                       RX_FLAG_MMIC_STRIPPED |
                       RX_FLAG_DECRYPTED;
 
-       wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
+       wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%llx\n", status.flag);
 
        memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 
-       hdr = (struct ieee80211_hdr *) skb->data;
-       fc = __le16_to_cpu(hdr->frame_control);
-       sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
-
        if (ieee80211_is_beacon(hdr->frame_control)) {
                wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
                            skb, skb->len, fc, sn);
@@ -221,7 +228,7 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
 
        /* default rate for unicast */
        if (ieee80211_is_mgmt(hdr->frame_control))
-               bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ?
+               bd->bd_rate = (WCN36XX_BAND(wcn) == NL80211_BAND_5GHZ) ?
                        WCN36XX_BD_RATE_CTRL :
                        WCN36XX_BD_RATE_MGMT;
        else if (ieee80211_is_ctl(hdr->frame_control))
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
deleted file mode 100644 (file)
index 9e7f820..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
- * Copyright (c) 2013 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/completion.h>
-#include <linux/firmware.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/remoteproc.h>
-#include <linux/soc/qcom/smd.h>
-#include "wcn36xx.h"
-
-#define MAC_ADDR_0 "wlan/macaddr0"
-
-struct smd_packet_item {
-       struct list_head list;
-       void *buf;
-       size_t count;
-};
-
-static int wcn36xx_msm_smsm_change_state(u32 clear_mask, u32 set_mask)
-{
-       return 0;
-}
-
-static int wcn36xx_msm_get_hw_mac(struct wcn36xx *wcn, u8 *addr)
-{
-       const struct firmware *addr_file = NULL;
-       int status;
-       u8 tmp[18];
-       static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
-       static const char *files = {MAC_ADDR_0};
-       struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
-
-       status = request_firmware(&addr_file, files, &pdata->core->dev);
-
-       if (status < 0) {
-               /* Assign a random mac with Qualcomm oui */
-               dev_err(&pdata->core->dev, "Failed (%d) to read macaddress"
-                       "file %s, using a random address instead", status, files);
-               memcpy(addr, qcom_oui, 3);
-               get_random_bytes(addr + 3, 3);
-       } else {
-               memset(tmp, 0, sizeof(tmp));
-               memcpy(tmp, addr_file->data, sizeof(tmp) - 1);
-               sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
-                      &addr[0],
-                      &addr[1],
-                      &addr[2],
-                      &addr[3],
-                      &addr[4],
-                      &addr[5]);
-
-               release_firmware(addr_file);
-       }
-
-       return 0;
-}
-
-static int wcn36xx_msm_smd_send_and_wait(struct wcn36xx *wcn, char *buf, size_t len)
-{
-       int ret = 0;
-       struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
-
-       mutex_lock(&pdata->wlan_ctrl_lock);
-       ret = qcom_smd_send(pdata->wlan_ctrl_channel, buf, len);
-       if (ret) {
-               dev_err(wcn->dev, "wlan ctrl channel tx failed\n");
-       }
-       mutex_unlock(&pdata->wlan_ctrl_lock);
-
-       return ret;
-}
-
-static int wcn36xx_msm_smd_open(struct wcn36xx *wcn, void *rsp_cb)
-{
-       struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
-
-       pdata->cb = rsp_cb;
-       return 0;
-}
-
-static void wcn36xx_msm_smd_close(struct wcn36xx *wcn)
-{
-       return;
-}
-
-static int wcn36xx_msm_get_chip_type(struct wcn36xx *wcn)
-{
-       struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data;
-       return pdata->chip_type;
-}
-
-static struct wcn36xx_platform_data wcn36xx_data = {
-       .ctrl_ops = {
-               .open = wcn36xx_msm_smd_open,
-               .close = wcn36xx_msm_smd_close,
-               .tx = wcn36xx_msm_smd_send_and_wait,
-               .get_hw_mac = wcn36xx_msm_get_hw_mac,
-               .smsm_change_state = wcn36xx_msm_smsm_change_state,
-               .get_chip_type = wcn36xx_msm_get_chip_type,
-       },
-};
-
-static void wlan_ctrl_smd_process(struct work_struct *worker)
-{
-       unsigned long flags;
-       struct wcn36xx_platform_data *pdata =
-               container_of(worker,
-                       struct wcn36xx_platform_data, packet_process_work);
-
-       spin_lock_irqsave(&pdata->packet_lock, flags);
-       while (!list_empty(&pdata->packet_list)) {
-               struct smd_packet_item *packet;
-
-               packet = list_first_entry(&pdata->packet_list,
-                               struct smd_packet_item, list);
-               list_del(&packet->list);
-               spin_unlock_irqrestore(&pdata->packet_lock, flags);
-               pdata->cb(pdata->wcn, packet->buf, packet->count);
-               kfree(packet->buf);
-               spin_lock_irqsave(&pdata->packet_lock, flags);
-       }
-       spin_unlock_irqrestore(&pdata->packet_lock, flags);
-}
-
-static int qcom_smd_wlan_ctrl_probe(struct qcom_smd_device *sdev)
-{
-       pr_info("%s: enter\n", __func__);
-        mutex_init(&wcn36xx_data.wlan_ctrl_lock);
-        init_completion(&wcn36xx_data.wlan_ctrl_ack);
-
-       wcn36xx_data.sdev = sdev;
-       spin_lock_init(&wcn36xx_data.packet_lock);
-       INIT_LIST_HEAD(&wcn36xx_data.packet_list);
-       INIT_WORK(&wcn36xx_data.packet_process_work, wlan_ctrl_smd_process);
-
-        dev_set_drvdata(&sdev->dev, &wcn36xx_data);
-       wcn36xx_data.wlan_ctrl_channel = sdev->channel;
-
-       wcn36xx_data.chip_type = (enum wcn36xx_chip_type)of_device_get_match_data(&sdev->dev);
-       wcn36xx_data.core = platform_device_alloc("wcn36xx", -1);
-       wcn36xx_data.core->dev.parent = &sdev->dev;
-       wcn36xx_data.core->dev.platform_data = &wcn36xx_data;
-
-       platform_device_add(wcn36xx_data.core);
-
-       of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev);
-
-        return 0;
-}
-
-static void qcom_smd_wlan_ctrl_remove(struct qcom_smd_device *sdev)
-{
-        of_platform_depopulate(&sdev->dev);
-       platform_device_del(wcn36xx_data.core);
-       platform_device_put(wcn36xx_data.core);
-}
-
-static int qcom_smd_wlan_ctrl_callback(struct qcom_smd_device *qsdev,
-                                 const void *data,
-                                 size_t count)
-{
-       unsigned long flags;
-       struct smd_packet_item *packet = NULL;
-       struct wcn36xx_platform_data *pdata = dev_get_drvdata(&qsdev->dev);
-       void *buf = kzalloc(count + sizeof(struct smd_packet_item),
-                               GFP_ATOMIC);
-       if (!buf) {
-               dev_err(&pdata->core->dev, "can't allocate buffer\n");
-               return -ENOMEM;
-       }
-
-       memcpy_fromio(buf, data, count);
-       packet = buf + count;
-       packet->buf = buf;
-       packet->count = count;
-
-       spin_lock_irqsave(&pdata->packet_lock, flags);
-       list_add_tail(&packet->list, &pdata->packet_list);
-       spin_unlock_irqrestore(&pdata->packet_lock, flags);
-       schedule_work(&pdata->packet_process_work);
-
-       /* buf will be freed in workqueue */
-
-       return 0;
-}
-
-static const struct of_device_id wcn36xx_msm_match_table[] = {
-       { .compatible = "qcom,wcn3660-wlan", .data = (void *)WCN36XX_CHIP_3660 },
-       { .compatible = "qcom,wcn3680-wlan", .data = (void *)WCN36XX_CHIP_3680 },
-       { .compatible = "qcom,wcn3620-wlan", .data = (void *)WCN36XX_CHIP_3620 },
-       { }
-};
-MODULE_DEVICE_TABLE(of, wcn36xx_msm_match_table);
-
-static struct qcom_smd_driver qcom_smd_wlan_ctrl_driver = {
-       .probe = qcom_smd_wlan_ctrl_probe,
-       .remove = qcom_smd_wlan_ctrl_remove,
-       .callback = qcom_smd_wlan_ctrl_callback,
-       .driver  = {
-               .name  = "qcom_smd_wlan_ctrl",
-               .owner = THIS_MODULE,
-               .of_match_table = wcn36xx_msm_match_table,
-       },
-};
-
-static int __init wcn36xx_msm_init(void)
-{
-       return qcom_smd_driver_register(&qcom_smd_wlan_ctrl_driver);
-}
-module_init(wcn36xx_msm_init);
-
-static void __exit wcn36xx_msm_exit(void)
-{
-}
-module_exit(wcn36xx_msm_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
-MODULE_FIRMWARE(MAC_ADDR_0);
-
index b17d284a69c9850758464a5d1569d69384aac994..35a6590c3ee51db0c5f9f2e3e1aa927e1b0531c8 100644 (file)
@@ -35,6 +35,9 @@
 /* How many frames until we start a-mpdu TX session */
 #define WCN36XX_AMPDU_START_THRESH     20
 
+#define WCN36XX_MAX_SCAN_SSIDS         9
+#define WCN36XX_MAX_SCAN_IE_LEN                500
+
 extern unsigned int wcn36xx_dbg_mask;
 
 enum wcn36xx_debug_mask {
@@ -103,49 +106,6 @@ struct nv_data {
        u8      table;
 };
 
-enum wcn36xx_chip_type {
-       WCN36XX_CHIP_UNKNOWN,
-       WCN36XX_CHIP_3660,
-       WCN36XX_CHIP_3680,
-       WCN36XX_CHIP_3620,
-};
-
-/* Interface for platform control path
- *
- * @open: hook must be called when wcn36xx wants to open control channel.
- * @tx: sends a buffer.
- */
-struct wcn36xx_platform_ctrl_ops {
-       int (*open)(struct wcn36xx *wcn, void *rsp_cb);
-       void (*close)(struct wcn36xx *wcn);
-       int (*tx)(struct wcn36xx *wcn, char *buf, size_t len);
-       int (*get_hw_mac)(struct wcn36xx *wcn, u8 *addr);
-       int (*get_chip_type)(struct wcn36xx *wcn);
-       int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
-};
-
-struct wcn36xx_platform_data {
-       enum wcn36xx_chip_type chip_type;
-
-       struct platform_device *core;
-
-       struct qcom_smd_device *sdev;
-        struct qcom_smd_channel *wlan_ctrl_channel;
-        struct completion wlan_ctrl_ack;
-        struct mutex wlan_ctrl_lock;
-
-       struct pinctrl *pinctrl;
-
-       struct wcn36xx *wcn;
-
-       void (*cb)(struct wcn36xx *wcn, void *buf, size_t len);
-       struct wcn36xx_platform_ctrl_ops ctrl_ops;
-
-       struct work_struct packet_process_work;
-       spinlock_t packet_lock;
-       struct list_head packet_list;
-};
-
 /**
  * struct wcn36xx_vif - holds VIF related fields
  *
@@ -223,7 +183,7 @@ struct wcn36xx {
        u8                      fw_minor;
        u8                      fw_major;
        u32                     fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
-       enum wcn36xx_chip_type  chip_version;
+       bool                    is_pronto;
 
        /* extra byte for the NULL termination */
        u8                      crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
@@ -232,10 +192,16 @@ struct wcn36xx {
        /* IRQs */
        int                     tx_irq;
        int                     rx_irq;
-       void __iomem            *mmio;
+       void __iomem            *ccu_base;
+       void __iomem            *dxe_base;
+
+       struct qcom_smd_channel *smd_channel;
+
+       struct qcom_smem_state  *tx_enable_state;
+       unsigned                tx_enable_state_bit;
+       struct qcom_smem_state  *tx_rings_empty_state;
+       unsigned                tx_rings_empty_state_bit;
 
-       struct wcn36xx_platform_data *wcn36xx_data;
-       struct wcn36xx_platform_ctrl_ops *ctrl_ops;
        /*
         * smd_buf must be protected with smd_mutex to garantee
         * that all messages are sent one after another
@@ -246,9 +212,15 @@ struct wcn36xx {
        struct completion       hal_rsp_compl;
        struct workqueue_struct *hal_ind_wq;
        struct work_struct      hal_ind_work;
-       struct mutex            hal_ind_mutex;
+       spinlock_t              hal_ind_lock;
        struct list_head        hal_ind_queue;
 
+       struct work_struct      scan_work;
+       struct cfg80211_scan_request *scan_req;
+       int                     scan_freq;
+       int                     scan_band;
+       struct mutex            scan_lock;
+
        /* DXE channels */
        struct wcn36xx_dxe_ch   dxe_tx_l_ch;    /* TX low */
        struct wcn36xx_dxe_ch   dxe_tx_h_ch;    /* TX high */