wl12xx: move to new firmware (6.1.3.50.49)
authorEliad Peller <eliad@wizery.com>
Wed, 2 Feb 2011 07:59:35 +0000 (09:59 +0200)
committerLuciano Coelho <coelho@ti.com>
Wed, 9 Feb 2011 00:51:42 +0000 (22:51 -0200)
This patch adds support for the new wl12xx firmware (Rev 6.1.3.50.49)

Since this fw is not backward compatible with previous fw versions,
a new fw (with different name) is being fetched.

(the patch is big because it contains all the required fw api changes.
splitting it into multiple patches will result in corrupted intermediate
commits)

Signed-off-by: Eliad Peller <eliad@wizery.com>
Reviewed-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
13 files changed:
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.h
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.h
drivers/net/wireless/wl12xx/wl12xx.h

index 84d94b259900175de74901a38e557cecee3ae49d..f2fbda06a129cee323e1c54edcc7f3b27ffb7d89 100644 (file)
@@ -947,9 +947,9 @@ out:
        return ret;
 }
 
-int wl1271_acx_mem_cfg(struct wl1271 *wl)
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
 {
-       struct wl1271_acx_config_memory *mem_conf;
+       struct wl1271_acx_ap_config_memory *mem_conf;
        int ret;
 
        wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -979,13 +979,45 @@ out:
        return ret;
 }
 
-int wl1271_acx_init_mem_config(struct wl1271 *wl)
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 {
+       struct wl1271_acx_sta_config_memory *mem_conf;
        int ret;
 
-       ret = wl1271_acx_mem_cfg(wl);
-       if (ret < 0)
-               return ret;
+       wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
+
+       mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+       if (!mem_conf) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* memory config */
+       mem_conf->num_stations = DEFAULT_NUM_STATIONS;
+       mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
+       mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
+       mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+       mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
+       mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
+       mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
+       mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
+       mem_conf->tx_min = wl->conf.mem.tx_min;
+
+       ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+                                  sizeof(*mem_conf));
+       if (ret < 0) {
+               wl1271_warning("wl1271 mem config failed: %d", ret);
+               goto out;
+       }
+
+out:
+       kfree(mem_conf);
+       return ret;
+}
+
+int wl1271_acx_init_mem_config(struct wl1271 *wl)
+{
+       int ret;
 
        wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
                                     GFP_KERNEL);
index 5bc0ca97bec443a224fde8f38ef9aba50dc2ab99..537fab40ed123852c18e6d901fea58222807763c 100644 (file)
@@ -802,7 +802,7 @@ struct acx_tx_config_options {
 #define ACX_TX_DESCRIPTORS    32
 #define ACX_NUM_SSID_PROFILES 1
 
-struct wl1271_acx_config_memory {
+struct wl1271_acx_ap_config_memory {
        struct acx_header header;
 
        u8 rx_mem_block_num;
@@ -812,6 +812,20 @@ struct wl1271_acx_config_memory {
        __le32 total_tx_descriptors;
 } __packed;
 
+struct wl1271_acx_sta_config_memory {
+       struct acx_header header;
+
+       u8 rx_mem_block_num;
+       u8 tx_min_mem_block_num;
+       u8 num_stations;
+       u8 num_ssid_profiles;
+       __le32 total_tx_descriptors;
+       u8 dyn_mem_enable;
+       u8 tx_free_req;
+       u8 rx_free_req;
+       u8 tx_min;
+} __packed;
+
 struct wl1271_acx_mem_map {
        struct acx_header header;
 
@@ -1202,6 +1216,8 @@ enum {
        ACX_HT_BSS_OPERATION        = 0x0058,
        ACX_COEX_ACTIVITY           = 0x0059,
        ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
+       ACX_GEN_FW_CMD              = 0x0070,
+       ACX_HOST_IF_CFG_BITMAP      = 0x0071,
        ACX_MAX_TX_FAILURE          = 0x0072,
        DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
        DOT11_CUR_TX_PWR            = 0x100D,
@@ -1210,10 +1226,7 @@ enum {
        DOT11_GROUP_ADDRESS_TBL     = 0x1014,
        ACX_PM_CONFIG               = 0x1016,
        ACX_CONFIG_PS               = 0x1017,
-
-       MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
-
-       MAX_IE = 0xFFFF
+       ACX_CONFIG_HANGOVER         = 0x1018,
 };
 
 
@@ -1255,7 +1268,8 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
                       u32 apsd_conf0, u32 apsd_conf1);
 int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
index 1bb8be5e805bf9943d03f8c17959ab49ae86928a..66d15e77da38bbca27982dabddf022e561d24b31 100644 (file)
@@ -286,6 +286,13 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
        join->rx_filter_options = cpu_to_le32(wl->rx_filter);
        join->bss_type = bss_type;
        join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+       /*
+        * for supported_rate_set, we should use wl->rate_set. however,
+        * it seems that acx_rate_policies doesn't affect full_rate, and
+        * since we want to avoid additional join, we'll use a 0xffffffff value,
+        * and let the fw find the actual supported rates
+        */
+       join->supported_rate_set = cpu_to_le32(0xffffffff);
 
        if (wl->band == IEEE80211_BAND_5GHZ)
                join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -454,7 +461,7 @@ out:
        return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
 {
        struct wl1271_cmd_ps_params *ps_params = NULL;
        int ret = 0;
@@ -468,10 +475,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
        }
 
        ps_params->ps_mode = ps_mode;
-       ps_params->send_null_data = send;
-       ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
-       ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
-       ps_params->null_data_rate = cpu_to_le32(rates);
 
        ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
                              sizeof(*ps_params), 0);
index 75128141400612d59af471f01a6bdde5a92f3924..54c12e71417e9ce50f60c6213bae219784371de6 100644 (file)
@@ -39,7 +39,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
                           size_t len);
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@@ -140,6 +140,7 @@ enum cmd_templ {
                                  * For CTS-to-self (FastCTS) mechanism
                                  * for BT/WLAN coexistence (SoftGemini). */
        CMD_TEMPL_ARP_RSP,
+       CMD_TEMPL_LINK_MEASUREMENT_REPORT,
 
        /* AP-mode specific */
        CMD_TEMPL_AP_BEACON = 13,
@@ -216,6 +217,7 @@ struct wl1271_cmd_join {
         * ACK or CTS frames).
         */
        __le32 basic_rate_set;
+       __le32 supported_rate_set;
        u8 dtim_interval;
        /*
         * bits 0-2: This bitwise field specifies the type
@@ -278,15 +280,7 @@ struct wl1271_cmd_ps_params {
        struct wl1271_cmd_header header;
 
        u8 ps_mode; /* STATION_* */
-       u8 send_null_data; /* Do we have to send NULL data packet ? */
-       u8 retries; /* Number of retires for the initial NULL data packet */
-
-        /*
-         * TUs during which the target stays awake after switching
-         * to power save mode.
-         */
-       u8 hang_over_period;
-       __le32 null_data_rate;
+       u8 padding[3];
 } __packed;
 
 /* HW encryption keys */
index c81aecd755e5e93382b3eaab9eb51f3781b3eccf..d8c1249193826097b04a05110f062165ddf557fa 100644 (file)
@@ -1151,6 +1151,34 @@ struct conf_ht_setting {
        u16 inactivity_timeout;
 };
 
+struct conf_memory_settings {
+       /* Disable/Enable dynamic memory */
+       u8 dynamic_memory;
+
+       /*
+        * Minimum required free tx memory blocks in order to assure optimum
+        * performence
+        *
+        * Range: 0-120
+        */
+       u8 min_req_tx_blocks;
+
+       /*
+        * Minimum required free rx memory blocks in order to assure optimum
+        * performence
+        *
+        * Range: 0-120
+        */
+       u8 min_req_rx_blocks;
+
+       /*
+        * Minimum number of mem blocks (free+used) guaranteed for TX
+        *
+        * Range: 0-120
+        */
+       u8 tx_min;
+};
+
 struct conf_drv_settings {
        struct conf_sg_settings sg;
        struct conf_rx_settings rx;
@@ -1162,6 +1190,7 @@ struct conf_drv_settings {
        struct conf_scan_settings scan;
        struct conf_rf_settings rf;
        struct conf_ht_setting ht;
+       struct conf_memory_settings mem;
 };
 
 #endif
index 3376a5de09d7ed8c13312cdf3448e2034531bcc9..1b170c5cc595f22dde0b1c494b7276059e278960 100644 (file)
@@ -135,20 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
                /* go to extremely low power mode */
                wl1271_ps_elp_sleep(wl);
                break;
-       case EVENT_EXIT_POWER_SAVE_FAIL:
-               wl1271_debug(DEBUG_PSM, "PSM exit failed");
-
-               if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-                       wl->psm_entry_retry = 0;
-                       break;
-               }
-
-               /* make sure the firmware goes to active mode - the frame to
-                  be sent next will indicate to the AP, that we are active. */
-               ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-                                        wl->basic_rate, false);
-               break;
-       case EVENT_EXIT_POWER_SAVE_SUCCESS:
        default:
                break;
        }
index 1d5ef670d48019ec86dd840d2200508dfe79e887..0e80886f3031fe740fa74b1ff4faaa4294f4e387 100644 (file)
@@ -75,8 +75,6 @@ enum {
 enum {
        EVENT_ENTER_POWER_SAVE_FAIL = 0,
        EVENT_ENTER_POWER_SAVE_SUCCESS,
-       EVENT_EXIT_POWER_SAVE_FAIL,
-       EVENT_EXIT_POWER_SAVE_SUCCESS,
 };
 
 struct event_debug_report {
index 70b3dc88a2195655e3a7d35dd90c078a28ff6438..62dc9839dd31bf088f7a729c765f1497d7ddb83b 100644 (file)
@@ -325,6 +325,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
        if (ret < 0)
                return ret;
 
+       /* PS config */
+       ret = wl1271_acx_config_ps(wl);
+       if (ret < 0)
+               return ret;
+
        ret = wl1271_sta_init_templates_config(wl);
        if (ret < 0)
                return ret;
@@ -367,6 +372,10 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
        if (ret < 0)
                return ret;
 
+       ret = wl1271_acx_sta_mem_cfg(wl);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
@@ -433,6 +442,10 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
        if (ret < 0)
                return ret;
 
+       ret = wl1271_acx_ap_mem_cfg(wl);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 522bb09c953524e76478730530b6de367376bb8f..91d681221286820dc908c94bba04213398460c7e 100644 (file)
@@ -298,6 +298,12 @@ static struct conf_drv_settings default_conf = {
                .tx_ba_win_size = 64,
                .inactivity_timeout = 10000,
        },
+       .mem = {
+               .dynamic_memory               = 0,
+               .min_req_tx_blocks            = 104,
+               .min_req_rx_blocks            = 22,
+               .tx_min                       = 27,
+       }
 };
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl);
@@ -524,13 +530,19 @@ static int wl1271_plt_init(struct wl1271 *wl)
 }
 
 static void wl1271_fw_status(struct wl1271 *wl,
-                            struct wl1271_fw_status *status)
+                            struct wl1271_fw_full_status *full_status)
 {
+       struct wl1271_fw_common_status *status = &full_status->common;
        struct timespec ts;
        u32 total = 0;
        int i;
 
-       wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+       if (wl->bss_type == BSS_TYPE_AP_BSS)
+               wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+                               sizeof(struct wl1271_fw_ap_status), false);
+       else
+               wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+                               sizeof(struct wl1271_fw_sta_status), false);
 
        wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
                     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -589,7 +601,7 @@ static void wl1271_irq_work(struct work_struct *work)
                loopcount--;
 
                wl1271_fw_status(wl, wl->fw_status);
-               intr = le32_to_cpu(wl->fw_status->intr);
+               intr = le32_to_cpu(wl->fw_status->common.intr);
                if (!intr) {
                        wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
                        spin_lock_irqsave(&wl->wl_lock, flags);
@@ -611,7 +623,7 @@ static void wl1271_irq_work(struct work_struct *work)
                        wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
                        /* check for tx results */
-                       if (wl->fw_status->tx_results_counter !=
+                       if (wl->fw_status->common.tx_results_counter !=
                            (wl->tx_results_count & 0xff))
                                wl1271_tx_complete(wl);
 
@@ -625,7 +637,7 @@ static void wl1271_irq_work(struct work_struct *work)
                                wl1271_tx_work_locked(wl);
                        }
 
-                       wl1271_rx(wl, wl->fw_status);
+                       wl1271_rx(wl, &wl->fw_status->common);
                }
 
                if (intr & WL1271_ACX_INTR_EVENT_A) {
index 60a3738eadb0c2e6cf99bbce22be10722cec5633..2d3086ae633866630baabc54c6f582042d3db832 100644 (file)
@@ -139,8 +139,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
                        return ret;
                }
 
-               ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
-                                        rates, send);
+               ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
                if (ret < 0)
                        return ret;
 
@@ -163,8 +162,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
                if (ret < 0)
                        return ret;
 
-               ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
-                                        rates, send);
+               ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
                if (ret < 0)
                        return ret;
 
index b0c6ddc2a9455b6064cd43831148c245ce122d46..00d250d8da1855c297d0ff01cab72b6f725f582c 100644 (file)
 #include "rx.h"
 #include "io.h"
 
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
+static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
                                  u32 drv_rx_counter)
 {
        return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
                RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
+static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
                                 u32 drv_rx_counter)
 {
        return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
@@ -134,7 +134,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
        return 0;
 }
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 {
        struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
        u32 buf_size;
index 8d048b36bbbaaf2d1fdf4c482bc67df6453c0369..4cef8fa3dee1efe9e6f9f004197748dba19d7d76 100644 (file)
@@ -119,7 +119,7 @@ struct wl1271_rx_descriptor {
        u8  reserved;
 } __packed;
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 void wl1271_set_default_filters(struct wl1271 *wl);
 
index d1de13fe7d9a0dafb9afd23b4b0ad5e4be01ddec..140e26f3bae97f741208bbfc07bcaab12ad8e5b2 100644 (file)
@@ -130,7 +130,7 @@ extern u32 wl12xx_debug_level;
 
 
 
-#define WL1271_FW_NAME "wl1271-fw.bin"
+#define WL1271_FW_NAME "wl1271-fw-2.bin"
 #define WL1271_AP_FW_NAME "wl1271-fw-ap.bin"
 
 #define WL1271_NVS_NAME "wl1271-nvs.bin"
@@ -214,8 +214,8 @@ struct wl1271_stats {
 /* Broadcast and Global links + links to stations */
 #define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
 
-/* FW status registers */
-struct wl1271_fw_status {
+/* FW status registers common for AP/STA */
+struct wl1271_fw_common_status {
        __le32 intr;
        u8  fw_rx_counter;
        u8  drv_rx_counter;
@@ -224,6 +224,11 @@ struct wl1271_fw_status {
        __le32 rx_pkt_descs[NUM_RX_PKT_DESC];
        __le32 tx_released_blks[NUM_TX_QUEUES];
        __le32 fw_localtime;
+} __packed;
+
+/* FW status registers for AP */
+struct wl1271_fw_ap_status {
+       struct wl1271_fw_common_status common;
 
        /* Next fields valid only in AP FW */
 
@@ -238,6 +243,24 @@ struct wl1271_fw_status {
        u8 padding_1[1];
 } __packed;
 
+/* FW status registers for STA */
+struct wl1271_fw_sta_status {
+       struct wl1271_fw_common_status common;
+
+       u8  tx_total;
+       u8  reserved1;
+       __le16 reserved2;
+} __packed;
+
+struct wl1271_fw_full_status {
+       union {
+               struct wl1271_fw_common_status common;
+               struct wl1271_fw_sta_status sta;
+               struct wl1271_fw_ap_status ap;
+       };
+} __packed;
+
+
 struct wl1271_rx_mem_pool_addr {
        u32 addr;
        u32 addr_extra;
@@ -445,7 +468,7 @@ struct wl1271 {
        u32 buffer_cmd;
        u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-       struct wl1271_fw_status *fw_status;
+       struct wl1271_fw_full_status *fw_status;
        struct wl1271_tx_hw_res_if *tx_res_if;
 
        struct ieee80211_vif *vif;