diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-11-05 21:51:34 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-11-05 21:51:34 +0100 |
commit | dce1ebabcb0ac12113487221663c2aba648dd244 (patch) | |
tree | edcf745d82290450b794acc61f4b98616d639883 | |
parent | Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | wlcore: save last regdom configuration on stop (diff) | |
download | linux-dce1ebabcb0ac12113487221663c2aba648dd244.tar.xz linux-dce1ebabcb0ac12113487221663c2aba648dd244.zip |
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/main.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/acx.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/conf.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/debugfs.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/event.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/hw_ops.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/init.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/io.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/scan.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/testmode.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 |
16 files changed, 175 insertions, 53 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 591526b99154..be7129ba16ad 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -333,11 +333,11 @@ static struct wlcore_conf wl12xx_conf = { .always = 0, }, .fwlog = { - .mode = WL12XX_FWLOG_ON_DEMAND, + .mode = WL12XX_FWLOG_CONTINUOUS, .mem_blocks = 2, .severity = 0, .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, - .output = WL12XX_FWLOG_OUTPUT_HOST, + .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, .threshold = 0, }, .rate = { @@ -717,6 +717,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl) goto out; } + wl->fw_mem_block_size = 256; + wl->fwlog_end = 0x2000000; + /* 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; @@ -1262,9 +1265,10 @@ static int wl12xx_boot(struct wl1271 *wl) 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; + wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID; + ret = wlcore_boot_run_firmware(wl); if (ret < 0) goto out; @@ -1648,6 +1652,11 @@ static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, return true; } +static u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) +{ + return hwaddr << 5; +} + static int wl12xx_setup(struct wl1271 *wl); static struct wlcore_ops wl12xx_ops = { @@ -1684,6 +1693,7 @@ static struct wlcore_ops wl12xx_ops = { .channel_switch = wl12xx_cmd_channel_switch, .pre_pkt_send = NULL, .set_peer_cap = wl12xx_set_peer_cap, + .convert_hwaddr = wl12xx_convert_hwaddr, .lnk_high_prio = wl12xx_lnk_high_prio, .lnk_low_prio = wl12xx_lnk_low_prio, }; diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index d0daca1d23bc..ec37b16585df 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -456,11 +456,11 @@ static struct wlcore_conf wl18xx_conf = { .always = 0, }, .fwlog = { - .mode = WL12XX_FWLOG_ON_DEMAND, + .mode = WL12XX_FWLOG_CONTINUOUS, .mem_blocks = 2, .severity = 0, .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, - .output = WL12XX_FWLOG_OUTPUT_HOST, + .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, .threshold = 0, }, .rate = { @@ -505,7 +505,7 @@ static struct wlcore_conf wl18xx_conf = { static struct wl18xx_priv_conf wl18xx_default_priv_conf = { .ht = { - .mode = HT_MODE_DEFAULT, + .mode = HT_MODE_WIDE, }, .phy = { .phy_standalone = 0x00, @@ -516,7 +516,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { .auto_detect = 0x00, .dedicated_fem = FEM_NONE, .low_band_component = COMPONENT_3_WAY_SWITCH, - .low_band_component_type = 0x04, + .low_band_component_type = 0x05, .high_band_component = COMPONENT_2_WAY_SWITCH, .high_band_component_type = 0x09, .tcxo_ldo_voltage = 0x00, @@ -556,15 +556,15 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .psat = 0, - .low_power_val = 0x08, - .med_power_val = 0x12, - .high_power_val = 0x18, - .low_power_val_2nd = 0x05, - .med_power_val_2nd = 0x0a, - .high_power_val_2nd = 0x14, .external_pa_dc2dc = 0, .number_of_assembled_ant2_4 = 2, .number_of_assembled_ant5 = 1, + .low_power_val = 0xff, + .med_power_val = 0xff, + .high_power_val = 0xff, + .low_power_val_2nd = 0xff, + .med_power_val_2nd = 0xff, + .high_power_val_2nd = 0xff, .tx_rf_margin = 1, }, }; @@ -686,6 +686,9 @@ static int wl18xx_identify_chip(struct wl1271 *wl) goto out; } + wl->fw_mem_block_size = 272; + wl->fwlog_end = 0x40000000; + wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; @@ -988,10 +991,11 @@ static int wl18xx_boot(struct wl1271 *wl) BA_SESSION_RX_CONSTRAINT_EVENT_ID | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | INACTIVE_STA_EVENT_ID | - MAX_TX_FAILURE_EVENT_ID | CHANNEL_SWITCH_COMPLETE_EVENT_ID | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; + wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; + ret = wlcore_boot_run_firmware(wl); if (ret < 0) goto out; @@ -1604,6 +1608,11 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, return lnk->allocated_pkts < thold; } +static u32 wl18xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) +{ + return hwaddr & ~0x80000000; +} + static int wl18xx_setup(struct wl1271 *wl); static struct wlcore_ops wl18xx_ops = { @@ -1641,6 +1650,7 @@ static struct wlcore_ops wl18xx_ops = { .pre_pkt_send = wl18xx_pre_pkt_send, .sta_rc_update = wl18xx_sta_rc_update, .set_peer_cap = wl18xx_set_peer_cap, + .convert_hwaddr = wl18xx_convert_hwaddr, .lnk_high_prio = wl18xx_lnk_high_prio, .lnk_low_prio = wl18xx_lnk_low_prio, }; diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 7a970cd9c555..ec83675a2446 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -162,7 +162,8 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, wl1271_debug(DEBUG_ACX, "acx mem map"); - ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); + ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, + sizeof(struct acx_header), len); if (ret < 0) return ret; @@ -722,6 +723,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, void *stats) wl1271_debug(DEBUG_ACX, "acx statistics"); ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, + sizeof(struct acx_header), wl->stats.fw_stats_len); if (ret < 0) { wl1271_warning("acx statistics failed: %d", ret); @@ -1470,8 +1472,8 @@ int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, tsf_info->role_id = wlvif->role_id; - ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, - tsf_info, sizeof(*tsf_info)); + ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, + sizeof(struct acx_header), sizeof(*tsf_info)); if (ret < 0) { wl1271_warning("acx tsf info interrogate failed"); goto out; @@ -1752,7 +1754,7 @@ int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, acx->role_id = wlvif->role_id; ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, - acx, sizeof(*acx)); + acx, sizeof(*acx), sizeof(*acx)); if (ret < 0) { wl1271_warning("acx roaming statistics failed: %d", ret); ret = -ENOMEM; diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 9e5416f8764d..34d9dfff2ad3 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -60,7 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, u16 status; u16 poll_count = 0; - if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) + if (WARN_ON(wl->state == WLCORE_STATE_RESTARTING && + id != CMD_STOP_FWLOGGER)) return -EIO; cmd = buf; @@ -845,7 +846,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_test); * @buf: buffer for the response, including all headers, must work with dma * @len: length of buf */ -int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) +int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, + size_t cmd_len, size_t res_len) { struct acx_header *acx = buf; int ret; @@ -854,10 +856,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) acx->id = cpu_to_le16(id); - /* payload length, does not include any headers */ - acx->len = cpu_to_le16(len - sizeof(*acx)); + /* response payload length, does not include any headers */ + acx->len = cpu_to_le16(res_len - sizeof(*acx)); - ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); + ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, cmd_len, res_len); if (ret < 0) wl1271_error("INTERROGATE command failed"); diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index fd34123047cd..323d4a856e4b 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -45,7 +45,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum ieee80211_band band, int channel); int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); 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_interrogate(struct wl1271 *wl, u16 id, void *buf, + size_t cmd_len, size_t res_len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, unsigned long valid_rets); diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 2b96ff821341..40995c42bef8 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h @@ -1274,6 +1274,9 @@ struct conf_rx_streaming_settings { u8 always; } __packed; +#define CONF_FWLOG_MIN_MEM_BLOCKS 2 +#define CONF_FWLOG_MAX_MEM_BLOCKS 16 + struct conf_fwlog { /* Continuous or on-demand */ u8 mode; @@ -1281,7 +1284,7 @@ struct conf_fwlog { /* * Number of memory blocks dedicated for the FW logger * - * Range: 1-3, or 0 to disable the FW logger + * Range: 2-16, or 0 to disable the FW logger */ u8 mem_blocks; diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e17630c2a849..89893c717025 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -437,6 +437,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, int res = 0; ssize_t ret; char *buf; + struct wl12xx_vif *wlvif; #define DRIVER_STATE_BUF_LEN 1024 @@ -450,12 +451,28 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ #x " = " fmt "\n", wl->x)) +#define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...) \ + (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ + #x " = " fmt "\n", args)) + #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + continue; + + DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, + wlvif->p2p ? "P2P-CL" : "STA"); + } + + wl12xx_for_each_wlvif_ap(wl, wlvif) + DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, + wlvif->p2p ? "P2P-GO" : "AP"); + DRIVER_STATE_PRINT_INT(tx_blocks_available); DRIVER_STATE_PRINT_INT(tx_allocated_blocks); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); @@ -474,7 +491,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(state); - DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(sg_enabled); diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 67f61689b49e..8d3b34965db3 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -266,6 +266,7 @@ int wl1271_event_unmask(struct wl1271 *wl) { int ret; + wl1271_debug(DEBUG_EVENT, "unmasking event_mask 0x%x", wl->event_mask); ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); if (ret < 0) return ret; diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 7fd260c02a0a..51f8d634d32f 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h @@ -222,6 +222,15 @@ wlcore_hw_set_peer_cap(struct wl1271 *wl, return 0; } +static inline u32 +wlcore_hw_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) +{ + if (!wl->ops->convert_hwaddr) + BUG_ON(1); + + return wl->ops->convert_hwaddr(wl, hwaddr); +} + static inline bool wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, struct wl1271_link *lnk) diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 5c6f11e157d9..7699f9d07e26 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c @@ -571,6 +571,12 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); if (ret < 0) return ret; + + /* unmask ap events */ + wl->event_mask |= wl->ap_event_mask; + ret = wl1271_event_unmask(wl); + if (ret < 0) + return ret; /* first STA, no APs */ } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { u8 sta_auth = wl->conf.conn.sta_sleep_auth; diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index af7d9f9b3b4d..07e3d6a049ad 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h @@ -165,8 +165,8 @@ static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, int physical; int addr; - /* Addresses are stored internally as addresses to 32 bytes blocks */ - addr = hwaddr << 5; + /* Convert from FW internal address which is chip arch dependent */ + addr = wl->ops->convert_hwaddr(wl, hwaddr); physical = wlcore_translate_addr(wl, addr); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index bbdd10632373..0368b9cbfb89 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -44,6 +44,7 @@ #define WL1271_BOOT_RETRIES 3 static char *fwlog_param; +static int fwlog_mem_blocks = -1; static int bug_on_recovery = -1; static int no_recovery = -1; @@ -291,6 +292,18 @@ static void wlcore_adjust_conf(struct wl1271 *wl) { /* Adjust settings according to optional module parameters */ + /* Firmware Logger params */ + if (fwlog_mem_blocks != -1) { + if (fwlog_mem_blocks >= CONF_FWLOG_MIN_MEM_BLOCKS && + fwlog_mem_blocks <= CONF_FWLOG_MAX_MEM_BLOCKS) { + wl->conf.fwlog.mem_blocks = fwlog_mem_blocks; + } else { + wl1271_error( + "Illegal fwlog_mem_blocks=%d using default %d", + fwlog_mem_blocks, wl->conf.fwlog.mem_blocks); + } + } + if (fwlog_param) { if (!strcmp(fwlog_param, "continuous")) { wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; @@ -780,6 +793,7 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) if (wl->state == WLCORE_STATE_ON) { wl->state = WLCORE_STATE_RESTARTING; set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); + wl1271_ps_elp_wakeup(wl); wlcore_disable_interrupts_nosync(wl); ieee80211_queue_work(wl->hw, &wl->recovery_work); } @@ -787,19 +801,10 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) { - size_t len = 0; - - /* The FW log is a length-value list, find where the log end */ - while (len < maxlen) { - if (memblock[len] == 0) - break; - if (len + memblock[len] + 1 > maxlen) - break; - len += memblock[len] + 1; - } + size_t len; /* Make sure we have enough room */ - len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size)); + len = min(maxlen, (size_t)(PAGE_SIZE - wl->fwlog_size)); /* Fill the FW log file, consumed by the sysfs fwlog entry */ memcpy(wl->fwlog + wl->fwlog_size, memblock, len); @@ -808,10 +813,9 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) return len; } -#define WLCORE_FW_LOG_END 0x2000000 - static void wl12xx_read_fwlog_panic(struct wl1271 *wl) { + struct wlcore_partition_set part, old_part; u32 addr; u32 offset; u32 end_of_log; @@ -824,7 +828,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) wl1271_info("Reading FW panic log"); - block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL); + block = kmalloc(wl->fw_mem_block_size, GFP_KERNEL); if (!block) return; @@ -850,17 +854,31 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); - end_of_log = WLCORE_FW_LOG_END; + end_of_log = wl->fwlog_end; } else { offset = sizeof(addr); end_of_log = addr; } + old_part = wl->curr_part; + memset(&part, 0, sizeof(part)); + /* Traverse the memory blocks linked list */ do { - memset(block, 0, WL12XX_HW_BLOCK_SIZE); - ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, - false); + part.mem.start = wlcore_hw_convert_hwaddr(wl, addr); + part.mem.size = PAGE_SIZE; + + ret = wlcore_set_partition(wl, &part); + if (ret < 0) { + wl1271_error("%s: set_partition start=0x%X size=%d", + __func__, part.mem.start, part.mem.size); + goto out; + } + + memset(block, 0, wl->fw_mem_block_size); + ret = wlcore_read_hwaddr(wl, addr, block, + wl->fw_mem_block_size, false); + if (ret < 0) goto out; @@ -871,8 +889,9 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) * on demand mode and is equal to 0x2000000 in continuous mode. */ addr = le32_to_cpup((__le32 *)block); + if (!wl12xx_copy_fwlog(wl, block + offset, - WL12XX_HW_BLOCK_SIZE - offset)) + wl->fw_mem_block_size - offset)) break; } while (addr && (addr != end_of_log)); @@ -880,6 +899,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) out: kfree(block); + wlcore_set_partition(wl, &old_part); } static void wlcore_print_recovery(struct wl1271 *wl) @@ -924,7 +944,8 @@ static void wl1271_recovery_work(struct work_struct *work) goto out_unlock; if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { - wl12xx_read_fwlog_panic(wl); + if (wl->conf.fwlog.output == WL12XX_FWLOG_OUTPUT_HOST) + wl12xx_read_fwlog_panic(wl); wlcore_print_recovery(wl); } @@ -1928,8 +1949,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) /* * FW channels must be re-calibrated after recovery, - * clear the last Reg-Domain channel configuration. + * save current Reg-Domain channel configuration and clear it. */ + memcpy(wl->reg_ch_conf_pending, wl->reg_ch_conf_last, + sizeof(wl->reg_ch_conf_pending)); memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); } @@ -2623,6 +2646,12 @@ deinit: !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) goto unlock; + if (wl->ap_count == 0 && is_ap) { + /* mask ap events */ + wl->event_mask &= ~wl->ap_event_mask; + wl1271_event_unmask(wl); + } + if (wl->ap_count == 0 && is_ap && wl->sta_count) { u8 sta_auth = wl->conf.conn.sta_sleep_auth; /* Configure for power according to debugfs */ @@ -6152,6 +6181,9 @@ module_param_named(fwlog, fwlog_param, charp, 0); MODULE_PARM_DESC(fwlog, "FW logger options: continuous, ondemand, dbgpins or disable"); +module_param(fwlog_mem_blocks, int, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(fwlog_mem_blocks, "fwlog mem_blocks"); + module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index 13e743df2e31..7ed86203304b 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -92,9 +92,31 @@ out: static void wlcore_started_vifs_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + bool active = false; int *count = (int *)data; - if (!vif->bss_conf.idle) + /* + * count active interfaces according to interface type. + * checking only bss_conf.idle is bad for some cases, e.g. + * we don't want to count sta in p2p_find as active interface. + */ + switch (wlvif->bss_type) { + case BSS_TYPE_STA_BSS: + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + active = true; + break; + + case BSS_TYPE_AP_BSS: + if (wlvif->wl->active_sta_count > 0) + active = true; + break; + + default: + break; + } + + if (active) (*count)++; } diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index a3b7d950d8e9..ddad58f614da 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -179,7 +179,8 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) goto out_sleep; } - ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); + ret = wl1271_cmd_interrogate(wl, ie_id, cmd, + sizeof(struct acx_header), sizeof(*cmd)); if (ret < 0) { wl1271_warning("testmode cmd interrogate failed: %d", ret); goto out_free; diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 54ce5d5e84db..06efc12a39e5 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -110,6 +110,7 @@ struct wlcore_ops { struct ieee80211_sta_ht_cap *ht_cap, bool allow_ht_operation, u32 rate_set, u8 hlid); + u32 (*convert_hwaddr)(struct wl1271 *wl, u32 hwaddr); bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, struct wl1271_link *lnk); bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, @@ -290,6 +291,12 @@ struct wl1271 { /* Number of valid bytes in the FW log buffer */ ssize_t fwlog_size; + /* FW log end marker */ + u32 fwlog_end; + + /* FW memory block size */ + u32 fw_mem_block_size; + /* Sysfs FW log entry readers wait queue */ wait_queue_head_t fwlog_waitq; @@ -307,6 +314,8 @@ struct wl1271 { /* The mbox event mask */ u32 event_mask; + /* events to unmask only when ap interface is up */ + u32 ap_event_mask; /* Mailbox pointers */ u32 mbox_size; diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 2a50e089b0e7..ce7261ce8b59 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -550,6 +550,4 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, #define HW_HT_RATES_OFFSET 16 #define HW_MIMO_RATES_OFFSET 24 -#define WL12XX_HW_BLOCK_SIZE 256 - #endif /* __WLCORE_I_H__ */ |