These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ti / wl18xx / main.c
index 717c4f5..50cce42 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/ip.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
+#include <linux/irq.h>
 
 #include "../wlcore/wlcore.h"
 #include "../wlcore/debug.h"
@@ -421,6 +422,8 @@ static struct wlcore_conf wl18xx_conf = {
                .num_probe_reqs                 = 2,
                .rssi_threshold                 = -90,
                .snr_threshold                  = 0,
+               .num_short_intervals            = SCAN_MAX_SHORT_INTERVALS,
+               .long_interval                  = 30000,
        },
        .ht = {
                .rx_ba_win_size = 32,
@@ -578,7 +581,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
 
 static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
        [PART_TOP_PRCM_ELP_SOC] = {
-               .mem  = { .start = 0x00A02000, .size  = 0x00010000 },
+               .mem  = { .start = 0x00A00000, .size  = 0x00012000 },
                .reg  = { .start = 0x00807000, .size  = 0x00005000 },
                .mem2 = { .start = 0x00800000, .size  = 0x0000B000 },
                .mem3 = { .start = 0x00000000, .size  = 0x00000000 },
@@ -862,6 +865,7 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
 {
        u32 tmp;
        int ret;
+       u16 irq_invert;
 
        BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) >
                WL18XX_PHY_INIT_MEM_SIZE);
@@ -911,6 +915,28 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
        /* re-enable FDSP clock */
        ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
                             MEM_FDSP_CLK_120_ENABLE);
+       if (ret < 0)
+               goto out;
+
+       ret = irq_get_trigger_type(wl->irq);
+       if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) {
+               wl1271_info("using inverted interrupt logic: %d", ret);
+               ret = wlcore_set_partition(wl,
+                                          &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+               if (ret < 0)
+                       goto out;
+
+               ret = wl18xx_top_reg_read(wl, TOP_FN0_CCCR_REG_32, &irq_invert);
+               if (ret < 0)
+                       goto out;
+
+               irq_invert |= BIT(1);
+               ret = wl18xx_top_reg_write(wl, TOP_FN0_CCCR_REG_32, irq_invert);
+               if (ret < 0)
+                       goto out;
+
+               ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
+       }
 
 out:
        return ret;
@@ -1002,8 +1028,8 @@ static int wl18xx_boot(struct wl1271 *wl)
                CHANNEL_SWITCH_COMPLETE_EVENT_ID |
                DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
                SMART_CONFIG_SYNC_EVENT_ID |
-               SMART_CONFIG_DECODE_EVENT_ID;
-;
+               SMART_CONFIG_DECODE_EVENT_ID |
+               TIME_SYNC_EVENT_ID;
 
        wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
 
@@ -1135,6 +1161,11 @@ static int wl18xx_hw_init(struct wl1271 *wl)
        if (ret < 0)
                return ret;
 
+       /* set the dynamic fw traces bitmap */
+       ret = wl18xx_acx_dynamic_fw_traces(wl);
+       if (ret < 0)
+               return ret;
+
        if (checksum_param) {
                ret = wl18xx_acx_set_checksum_state(wl);
                if (ret != 0)
@@ -1351,9 +1382,10 @@ out:
 }
 
 #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
-static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
+
+static int wl18xx_load_conf_file(struct device *dev, struct wlcore_conf *conf,
+                                struct wl18xx_priv_conf *priv_conf)
 {
-       struct wl18xx_priv *priv = wl->priv;
        struct wlcore_conf_file *conf_file;
        const struct firmware *fw;
        int ret;
@@ -1362,14 +1394,14 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
        if (ret < 0) {
                wl1271_error("could not get configuration binary %s: %d",
                             WL18XX_CONF_FILE_NAME, ret);
-               goto out_fallback;
+               return ret;
        }
 
        if (fw->size != WL18XX_CONF_SIZE) {
                wl1271_error("configuration binary file size is wrong, expected %zu got %zu",
                             WL18XX_CONF_SIZE, fw->size);
                ret = -EINVAL;
-               goto out;
+               goto out_release;
        }
 
        conf_file = (struct wlcore_conf_file *) fw->data;
@@ -1379,7 +1411,7 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
                             "expected 0x%0x got 0x%0x", WL18XX_CONF_MAGIC,
                             conf_file->header.magic);
                ret = -EINVAL;
-               goto out;
+               goto out_release;
        }
 
        if (conf_file->header.version != cpu_to_le32(WL18XX_CONF_VERSION)) {
@@ -1387,28 +1419,32 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
                             "expected 0x%08x got 0x%08x",
                             WL18XX_CONF_VERSION, conf_file->header.version);
                ret = -EINVAL;
-               goto out;
+               goto out_release;
        }
 
-       memcpy(&wl->conf, &conf_file->core, sizeof(wl18xx_conf));
-       memcpy(&priv->conf, &conf_file->priv, sizeof(priv->conf));
+       memcpy(conf, &conf_file->core, sizeof(*conf));
+       memcpy(priv_conf, &conf_file->priv, sizeof(*priv_conf));
 
-       goto out;
+out_release:
+       release_firmware(fw);
+       return ret;
+}
+
+static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
+{
+       struct wl18xx_priv *priv = wl->priv;
 
-out_fallback:
-       wl1271_warning("falling back to default config");
+       if (wl18xx_load_conf_file(dev, &wl->conf, &priv->conf) < 0) {
+               wl1271_warning("falling back to default config");
 
-       /* apply driver default configuration */
-       memcpy(&wl->conf, &wl18xx_conf, sizeof(wl18xx_conf));
-       /* apply default private configuration */
-       memcpy(&priv->conf, &wl18xx_default_priv_conf, sizeof(priv->conf));
+               /* apply driver default configuration */
+               memcpy(&wl->conf, &wl18xx_conf, sizeof(wl->conf));
+               /* apply default private configuration */
+               memcpy(&priv->conf, &wl18xx_default_priv_conf,
+                      sizeof(priv->conf));
+       }
 
-       /* For now we just fallback */
        return 0;
-
-out:
-       release_firmware(fw);
-       return ret;
 }
 
 static int wl18xx_plt_init(struct wl1271 *wl)
@@ -1768,7 +1804,7 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
 
 static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
        {
-               .max = 3,
+               .max = 2,
                .types = BIT(NL80211_IFTYPE_STATION),
        },
        {
@@ -1777,6 +1813,10 @@ static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
                         BIT(NL80211_IFTYPE_P2P_GO) |
                         BIT(NL80211_IFTYPE_P2P_CLIENT),
        },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
 };
 
 static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
@@ -1784,6 +1824,48 @@ static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
                .max = 2,
                .types = BIT(NL80211_IFTYPE_AP),
        },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
+};
+
+static const struct ieee80211_iface_limit wl18xx_iface_ap_cl_limits[] = {
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_AP),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
+};
+
+static const struct ieee80211_iface_limit wl18xx_iface_ap_go_limits[] = {
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_AP),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_GO),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
 };
 
 static const struct ieee80211_iface_combination
@@ -2033,3 +2115,4 @@ MODULE_PARM_DESC(num_rx_desc_param,
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_FIRMWARE(WL18XX_FW_NAME);
+MODULE_FIRMWARE(WL18XX_CONF_FILE_NAME);