diff options
Diffstat (limited to 'drivers/net/wireless/ti/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/main.c | 192 |
1 files changed, 140 insertions, 52 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index e5f5f8f3914..3254bfc81a2 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -38,6 +38,8 @@ #include "reg.h" #include "cmd.h" #include "acx.h" +#include "scan.h" +#include "event.h" #include "debugfs.h" static char *fref_param; @@ -208,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = { .tmpl_short_retry_limit = 10, .tmpl_long_retry_limit = 10, .tx_watchdog_timeout = 5000, + .slow_link_thold = 3, + .fast_link_thold = 10, }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, @@ -265,8 +269,10 @@ static struct wlcore_conf wl12xx_conf = { .scan = { .min_dwell_time_active = 7500, .max_dwell_time_active = 30000, - .min_dwell_time_passive = 100000, - .max_dwell_time_passive = 100000, + .min_dwell_time_active_long = 25000, + .max_dwell_time_active_long = 50000, + .dwell_time_passive = 100000, + .dwell_time_dfs = 150000, .num_probe_reqs = 2, .split_scan_timeout = 50000, }, @@ -368,6 +374,10 @@ static struct wlcore_conf wl12xx_conf = { .increase_time = 1, .window_size = 16, }, + .recovery = { + .bug_on_recovery = 0, + .no_recovery = 0, + }, }; static struct wl12xx_priv_conf wl12xx_default_priv_conf = { @@ -601,9 +611,9 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) { int ret; - if (wl->chip.id != CHIP_ID_1283_PG20) { + if (wl->chip.id != CHIP_ID_128X_PG20) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; - struct wl127x_rx_mem_pool_addr rx_mem_addr; + struct wl12xx_priv *priv = wl->priv; /* * Choose the block we want to read @@ -612,13 +622,13 @@ static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) */ u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK; - rx_mem_addr.addr = (mem_block << 8) + + priv->rx_mem_addr->addr = (mem_block << 8) + le32_to_cpu(wl_mem_map->packet_memory_pool_start); - rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; + priv->rx_mem_addr->addr_extra = priv->rx_mem_addr->addr + 4; - ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr, - sizeof(rx_mem_addr), false); + ret = wlcore_write(wl, WL1271_SLV_REG_DATA, priv->rx_mem_addr, + sizeof(*priv->rx_mem_addr), false); if (ret < 0) return ret; } @@ -631,13 +641,15 @@ static int wl12xx_identify_chip(struct wl1271 *wl) int ret = 0; switch (wl->chip.id) { - case CHIP_ID_1271_PG10: + case CHIP_ID_127X_PG10: wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", wl->chip.id); wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | WLCORE_QUIRK_DUAL_PROBE_TMPL | - WLCORE_QUIRK_TKIP_HEADER_SPACE; + WLCORE_QUIRK_TKIP_HEADER_SPACE | + WLCORE_QUIRK_START_STA_FAILS | + WLCORE_QUIRK_AP_ZERO_SESSION_ID; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, @@ -646,18 +658,22 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* read data preparation is only needed by wl127x */ wl->ops->prepare_read = wl127x_prepare_read; - wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, - WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, - WL127X_MINOR_VER); + wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, + WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, + WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, + WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, + WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); break; - case CHIP_ID_1271_PG20: + case CHIP_ID_127X_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", wl->chip.id); wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | WLCORE_QUIRK_DUAL_PROBE_TMPL | - WLCORE_QUIRK_TKIP_HEADER_SPACE; + WLCORE_QUIRK_TKIP_HEADER_SPACE | + WLCORE_QUIRK_START_STA_FAILS | + WLCORE_QUIRK_AP_ZERO_SESSION_ID; wl->plt_fw_name = WL127X_PLT_FW_NAME; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; @@ -667,12 +683,14 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* read data preparation is only needed by wl127x */ wl->ops->prepare_read = wl127x_prepare_read; - wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER, - WL127X_MAJOR_VER, WL127X_SUBTYPE_VER, - WL127X_MINOR_VER); + wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, + WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, + WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER, + WL127X_IFTYPE_MR_VER, WL127X_MAJOR_MR_VER, + WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER); break; - case CHIP_ID_1283_PG20: + case CHIP_ID_128X_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", wl->chip.id); wl->plt_fw_name = WL128X_PLT_FW_NAME; @@ -682,19 +700,29 @@ static int wl12xx_identify_chip(struct wl1271 *wl) /* wl128x requires TX blocksize alignment */ wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | WLCORE_QUIRK_DUAL_PROBE_TMPL | - WLCORE_QUIRK_TKIP_HEADER_SPACE; - - wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER, - WL128X_MAJOR_VER, WL128X_SUBTYPE_VER, - WL128X_MINOR_VER); + WLCORE_QUIRK_TKIP_HEADER_SPACE | + WLCORE_QUIRK_START_STA_FAILS | + WLCORE_QUIRK_AP_ZERO_SESSION_ID; + + wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, + WL128X_IFTYPE_SR_VER, WL128X_MAJOR_SR_VER, + WL128X_SUBTYPE_SR_VER, WL128X_MINOR_SR_VER, + WL128X_IFTYPE_MR_VER, WL128X_MAJOR_MR_VER, + WL128X_SUBTYPE_MR_VER, WL128X_MINOR_MR_VER); break; - case CHIP_ID_1283_PG10: + case CHIP_ID_128X_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); ret = -ENODEV; goto out; } + /* common settings */ + wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; + wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; + wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; + wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; + wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; out: return ret; } @@ -1067,7 +1095,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) u32 clk; int selected_clock = -1; - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { ret = wl128x_boot_clk(wl, &selected_clock); if (ret < 0) goto out; @@ -1098,7 +1126,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - if (wl->chip.id == CHIP_ID_1283_PG20) + if (wl->chip.id == CHIP_ID_128X_PG20) clk |= ((selected_clock & 0x3) << 1) << 4; else clk |= (priv->ref_clock << 1) << 4; @@ -1152,7 +1180,7 @@ static int wl12xx_pre_upload(struct wl1271 *wl) /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); if (ret < 0) goto out; @@ -1219,6 +1247,23 @@ static int wl12xx_boot(struct wl1271 *wl) if (ret < 0) goto out; + wl->event_mask = BSS_LOSE_EVENT_ID | + REGAINED_BSS_EVENT_ID | + SCAN_COMPLETE_EVENT_ID | + ROLE_STOP_COMPLETE_EVENT_ID | + RSSI_SNR_TRIGGER_0_EVENT_ID | + PSPOLL_DELIVERY_FAILURE_EVENT_ID | + SOFT_GEMINI_SENSE_EVENT_ID | + PERIODIC_SCAN_REPORT_EVENT_ID | + PERIODIC_SCAN_COMPLETE_EVENT_ID | + DUMMY_PACKET_EVENT_ID | + PEER_REMOVE_COMPLETE_EVENT_ID | + BA_SESSION_RX_CONSTRAINT_EVENT_ID | + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | + INACTIVE_STA_EVENT_ID | + MAX_TX_RETRY_EVENT_ID | + CHANNEL_SWITCH_COMPLETE_EVENT_ID; + ret = wlcore_boot_run_firmware(wl); if (ret < 0) goto out; @@ -1261,7 +1306,7 @@ static void wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, u32 blks, u32 spare_blks) { - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { desc->wl128x_mem.total_mem_blocks = blks; } else { desc->wl127x_mem.extra_blocks = spare_blks; @@ -1275,7 +1320,7 @@ wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, { u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len); - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { desc->wl128x_mem.extra_bytes = aligned_len - skb->len; desc->length = cpu_to_le16(aligned_len >> 2); @@ -1339,7 +1384,7 @@ static int wl12xx_hw_init(struct wl1271 *wl) { int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; ret = wl128x_cmd_general_parms(wl); @@ -1394,22 +1439,6 @@ static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, return wlvif->rate_set; } -static int wl12xx_identify_fw(struct wl1271 *wl) -{ - unsigned int *fw_ver = wl->chip.fw_ver; - - /* Only new station firmwares support routing fw logs to the host */ - if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && - (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) - wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; - - /* This feature is not yet supported for AP mode */ - if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) - wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; - - return 0; -} - static void wl12xx_conf_init(struct wl1271 *wl) { struct wl12xx_priv *priv = wl->priv; @@ -1426,7 +1455,7 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl) bool supported = false; u8 major, minor; - if (wl->chip.id == CHIP_ID_1283_PG20) { + if (wl->chip.id == CHIP_ID_128X_PG20) { major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); @@ -1482,7 +1511,7 @@ static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) u16 die_info; int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) + if (wl->chip.id == CHIP_ID_128X_PG20) ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, &die_info); else @@ -1589,16 +1618,46 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return wlcore_set_key(wl, cmd, vif, sta, key_conf); } +static int wl12xx_set_peer_cap(struct wl1271 *wl, + struct ieee80211_sta_ht_cap *ht_cap, + bool allow_ht_operation, + u32 rate_set, u8 hlid) +{ + return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation, + hlid); +} + +static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, + struct wl1271_link *lnk) +{ + u8 thold; + + if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map)) + thold = wl->conf.tx.fast_link_thold; + else + thold = wl->conf.tx.slow_link_thold; + + return lnk->allocated_pkts < thold; +} + +static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, + struct wl1271_link *lnk) +{ + /* any link is good for low priority */ + return true; +} + static int wl12xx_setup(struct wl1271 *wl); static struct wlcore_ops wl12xx_ops = { .setup = wl12xx_setup, .identify_chip = wl12xx_identify_chip, - .identify_fw = wl12xx_identify_fw, .boot = wl12xx_boot, .plt_init = wl12xx_plt_init, .trigger_cmd = wl12xx_trigger_cmd, .ack_event = wl12xx_ack_event, + .wait_for_event = wl12xx_wait_for_event, + .process_mailbox_events = wl12xx_process_mailbox_events, .calc_tx_blocks = wl12xx_calc_tx_blocks, .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, @@ -1615,9 +1674,17 @@ static struct wlcore_ops wl12xx_ops = { .set_rx_csum = NULL, .ap_get_mimo_wide_rate_mask = NULL, .debugfs_init = wl12xx_debugfs_add_files, + .scan_start = wl12xx_scan_start, + .scan_stop = wl12xx_scan_stop, + .sched_scan_start = wl12xx_sched_scan_start, + .sched_scan_stop = wl12xx_scan_sched_scan_stop, .get_spare_blocks = wl12xx_get_spare_blocks, .set_key = wl12xx_set_key, + .channel_switch = wl12xx_cmd_channel_switch, .pre_pkt_send = NULL, + .set_peer_cap = wl12xx_set_peer_cap, + .lnk_high_prio = wl12xx_lnk_high_prio, + .lnk_low_prio = wl12xx_lnk_low_prio, }; static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { @@ -1641,6 +1708,7 @@ static int wl12xx_setup(struct wl1271 *wl) wl->rtable = wl12xx_rtable; wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; + wl->num_channels = 1; wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; @@ -1693,6 +1761,10 @@ static int wl12xx_setup(struct wl1271 *wl) wl1271_error("Invalid tcxo parameter %s", tcxo_param); } + priv->rx_mem_addr = kmalloc(sizeof(*priv->rx_mem_addr), GFP_KERNEL); + if (!priv->rx_mem_addr) + return -ENOMEM; + return 0; } @@ -1703,7 +1775,8 @@ static int wl12xx_probe(struct platform_device *pdev) int ret; hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), - WL12XX_AGGR_BUFFER_SIZE); + WL12XX_AGGR_BUFFER_SIZE, + sizeof(struct wl12xx_event_mailbox)); if (IS_ERR(hw)) { wl1271_error("can't allocate hw"); ret = PTR_ERR(hw); @@ -1725,6 +1798,21 @@ out: return ret; } +static int wl12xx_remove(struct platform_device *pdev) +{ + struct wl1271 *wl = platform_get_drvdata(pdev); + struct wl12xx_priv *priv; + + if (!wl) + goto out; + priv = wl->priv; + + kfree(priv->rx_mem_addr); + +out: + return wlcore_remove(pdev); +} + static const struct platform_device_id wl12xx_id_table[] = { { "wl12xx", 0 }, { } /* Terminating Entry */ @@ -1733,7 +1821,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table); static struct platform_driver wl12xx_driver = { .probe = wl12xx_probe, - .remove = wlcore_remove, + .remove = wl12xx_remove, .id_table = wl12xx_id_table, .driver = { .name = "wl12xx_driver", |