Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
@@ -333,11 +333,11 @@ static struct wlcore_conf wl12xx_conf = {
|
|||||||
.always = 0,
|
.always = 0,
|
||||||
},
|
},
|
||||||
.fwlog = {
|
.fwlog = {
|
||||||
.mode = WL12XX_FWLOG_ON_DEMAND,
|
.mode = WL12XX_FWLOG_CONTINUOUS,
|
||||||
.mem_blocks = 2,
|
.mem_blocks = 2,
|
||||||
.severity = 0,
|
.severity = 0,
|
||||||
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
|
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
|
||||||
.output = WL12XX_FWLOG_OUTPUT_HOST,
|
.output = WL12XX_FWLOG_OUTPUT_DBG_PINS,
|
||||||
.threshold = 0,
|
.threshold = 0,
|
||||||
},
|
},
|
||||||
.rate = {
|
.rate = {
|
||||||
@@ -717,6 +717,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl->fw_mem_block_size = 256;
|
||||||
|
wl->fwlog_end = 0x2000000;
|
||||||
|
|
||||||
/* common settings */
|
/* common settings */
|
||||||
wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY;
|
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->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 |
|
BA_SESSION_RX_CONSTRAINT_EVENT_ID |
|
||||||
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
|
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
|
||||||
INACTIVE_STA_EVENT_ID |
|
INACTIVE_STA_EVENT_ID |
|
||||||
MAX_TX_RETRY_EVENT_ID |
|
|
||||||
CHANNEL_SWITCH_COMPLETE_EVENT_ID;
|
CHANNEL_SWITCH_COMPLETE_EVENT_ID;
|
||||||
|
|
||||||
|
wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID;
|
||||||
|
|
||||||
ret = wlcore_boot_run_firmware(wl);
|
ret = wlcore_boot_run_firmware(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1648,6 +1652,11 @@ static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr)
|
||||||
|
{
|
||||||
|
return hwaddr << 5;
|
||||||
|
}
|
||||||
|
|
||||||
static int wl12xx_setup(struct wl1271 *wl);
|
static int wl12xx_setup(struct wl1271 *wl);
|
||||||
|
|
||||||
static struct wlcore_ops wl12xx_ops = {
|
static struct wlcore_ops wl12xx_ops = {
|
||||||
@@ -1684,6 +1693,7 @@ static struct wlcore_ops wl12xx_ops = {
|
|||||||
.channel_switch = wl12xx_cmd_channel_switch,
|
.channel_switch = wl12xx_cmd_channel_switch,
|
||||||
.pre_pkt_send = NULL,
|
.pre_pkt_send = NULL,
|
||||||
.set_peer_cap = wl12xx_set_peer_cap,
|
.set_peer_cap = wl12xx_set_peer_cap,
|
||||||
|
.convert_hwaddr = wl12xx_convert_hwaddr,
|
||||||
.lnk_high_prio = wl12xx_lnk_high_prio,
|
.lnk_high_prio = wl12xx_lnk_high_prio,
|
||||||
.lnk_low_prio = wl12xx_lnk_low_prio,
|
.lnk_low_prio = wl12xx_lnk_low_prio,
|
||||||
};
|
};
|
||||||
|
@@ -456,11 +456,11 @@ static struct wlcore_conf wl18xx_conf = {
|
|||||||
.always = 0,
|
.always = 0,
|
||||||
},
|
},
|
||||||
.fwlog = {
|
.fwlog = {
|
||||||
.mode = WL12XX_FWLOG_ON_DEMAND,
|
.mode = WL12XX_FWLOG_CONTINUOUS,
|
||||||
.mem_blocks = 2,
|
.mem_blocks = 2,
|
||||||
.severity = 0,
|
.severity = 0,
|
||||||
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
|
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
|
||||||
.output = WL12XX_FWLOG_OUTPUT_HOST,
|
.output = WL12XX_FWLOG_OUTPUT_DBG_PINS,
|
||||||
.threshold = 0,
|
.threshold = 0,
|
||||||
},
|
},
|
||||||
.rate = {
|
.rate = {
|
||||||
@@ -505,7 +505,7 @@ static struct wlcore_conf wl18xx_conf = {
|
|||||||
|
|
||||||
static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
|
static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
|
||||||
.ht = {
|
.ht = {
|
||||||
.mode = HT_MODE_DEFAULT,
|
.mode = HT_MODE_WIDE,
|
||||||
},
|
},
|
||||||
.phy = {
|
.phy = {
|
||||||
.phy_standalone = 0x00,
|
.phy_standalone = 0x00,
|
||||||
@@ -516,7 +516,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
|
|||||||
.auto_detect = 0x00,
|
.auto_detect = 0x00,
|
||||||
.dedicated_fem = FEM_NONE,
|
.dedicated_fem = FEM_NONE,
|
||||||
.low_band_component = COMPONENT_3_WAY_SWITCH,
|
.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 = COMPONENT_2_WAY_SWITCH,
|
||||||
.high_band_component_type = 0x09,
|
.high_band_component_type = 0x09,
|
||||||
.tcxo_ldo_voltage = 0x00,
|
.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,
|
.per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff },
|
0xff, 0xff, 0xff },
|
||||||
.psat = 0,
|
.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,
|
.external_pa_dc2dc = 0,
|
||||||
.number_of_assembled_ant2_4 = 2,
|
.number_of_assembled_ant2_4 = 2,
|
||||||
.number_of_assembled_ant5 = 1,
|
.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,
|
.tx_rf_margin = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -686,6 +686,9 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
|
|||||||
goto out;
|
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_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
|
||||||
wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
|
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;
|
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 |
|
BA_SESSION_RX_CONSTRAINT_EVENT_ID |
|
||||||
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
|
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
|
||||||
INACTIVE_STA_EVENT_ID |
|
INACTIVE_STA_EVENT_ID |
|
||||||
MAX_TX_FAILURE_EVENT_ID |
|
|
||||||
CHANNEL_SWITCH_COMPLETE_EVENT_ID |
|
CHANNEL_SWITCH_COMPLETE_EVENT_ID |
|
||||||
DFS_CHANNELS_CONFIG_COMPLETE_EVENT;
|
DFS_CHANNELS_CONFIG_COMPLETE_EVENT;
|
||||||
|
|
||||||
|
wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
|
||||||
|
|
||||||
ret = wlcore_boot_run_firmware(wl);
|
ret = wlcore_boot_run_firmware(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1604,6 +1608,11 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
|
|||||||
return lnk->allocated_pkts < thold;
|
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 int wl18xx_setup(struct wl1271 *wl);
|
||||||
|
|
||||||
static struct wlcore_ops wl18xx_ops = {
|
static struct wlcore_ops wl18xx_ops = {
|
||||||
@@ -1641,6 +1650,7 @@ static struct wlcore_ops wl18xx_ops = {
|
|||||||
.pre_pkt_send = wl18xx_pre_pkt_send,
|
.pre_pkt_send = wl18xx_pre_pkt_send,
|
||||||
.sta_rc_update = wl18xx_sta_rc_update,
|
.sta_rc_update = wl18xx_sta_rc_update,
|
||||||
.set_peer_cap = wl18xx_set_peer_cap,
|
.set_peer_cap = wl18xx_set_peer_cap,
|
||||||
|
.convert_hwaddr = wl18xx_convert_hwaddr,
|
||||||
.lnk_high_prio = wl18xx_lnk_high_prio,
|
.lnk_high_prio = wl18xx_lnk_high_prio,
|
||||||
.lnk_low_prio = wl18xx_lnk_low_prio,
|
.lnk_low_prio = wl18xx_lnk_low_prio,
|
||||||
};
|
};
|
||||||
|
@@ -162,7 +162,8 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
|
|||||||
|
|
||||||
wl1271_debug(DEBUG_ACX, "acx 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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -722,6 +723,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, void *stats)
|
|||||||
wl1271_debug(DEBUG_ACX, "acx statistics");
|
wl1271_debug(DEBUG_ACX, "acx statistics");
|
||||||
|
|
||||||
ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
|
ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
|
||||||
|
sizeof(struct acx_header),
|
||||||
wl->stats.fw_stats_len);
|
wl->stats.fw_stats_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_warning("acx statistics failed: %d", ret);
|
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;
|
tsf_info->role_id = wlvif->role_id;
|
||||||
|
|
||||||
ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO,
|
ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info,
|
||||||
tsf_info, sizeof(*tsf_info));
|
sizeof(struct acx_header), sizeof(*tsf_info));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_warning("acx tsf info interrogate failed");
|
wl1271_warning("acx tsf info interrogate failed");
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1752,7 +1754,7 @@ int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||||||
|
|
||||||
acx->role_id = wlvif->role_id;
|
acx->role_id = wlvif->role_id;
|
||||||
ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
|
ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
|
||||||
acx, sizeof(*acx));
|
acx, sizeof(*acx), sizeof(*acx));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_warning("acx roaming statistics failed: %d", ret);
|
wl1271_warning("acx roaming statistics failed: %d", ret);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@@ -60,7 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf,
|
|||||||
u16 status;
|
u16 status;
|
||||||
u16 poll_count = 0;
|
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;
|
return -EIO;
|
||||||
|
|
||||||
cmd = buf;
|
cmd = buf;
|
||||||
@@ -845,7 +846,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_test);
|
|||||||
* @buf: buffer for the response, including all headers, must work with dma
|
* @buf: buffer for the response, including all headers, must work with dma
|
||||||
* @len: length of buf
|
* @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;
|
struct acx_header *acx = buf;
|
||||||
int ret;
|
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);
|
acx->id = cpu_to_le16(id);
|
||||||
|
|
||||||
/* payload length, does not include any headers */
|
/* response payload length, does not include any headers */
|
||||||
acx->len = cpu_to_le16(len - sizeof(*acx));
|
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)
|
if (ret < 0)
|
||||||
wl1271_error("INTERROGATE command failed");
|
wl1271_error("INTERROGATE command failed");
|
||||||
|
|
||||||
|
@@ -45,7 +45,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||||||
enum ieee80211_band band, int channel);
|
enum ieee80211_band band, int channel);
|
||||||
int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
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_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 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,
|
int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf,
|
||||||
size_t len, unsigned long valid_rets);
|
size_t len, unsigned long valid_rets);
|
||||||
|
@@ -1274,6 +1274,9 @@ struct conf_rx_streaming_settings {
|
|||||||
u8 always;
|
u8 always;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define CONF_FWLOG_MIN_MEM_BLOCKS 2
|
||||||
|
#define CONF_FWLOG_MAX_MEM_BLOCKS 16
|
||||||
|
|
||||||
struct conf_fwlog {
|
struct conf_fwlog {
|
||||||
/* Continuous or on-demand */
|
/* Continuous or on-demand */
|
||||||
u8 mode;
|
u8 mode;
|
||||||
@@ -1281,7 +1284,7 @@ struct conf_fwlog {
|
|||||||
/*
|
/*
|
||||||
* Number of memory blocks dedicated for the FW logger
|
* 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;
|
u8 mem_blocks;
|
||||||
|
|
||||||
|
@@ -437,6 +437,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
struct wl12xx_vif *wlvif;
|
||||||
|
|
||||||
#define DRIVER_STATE_BUF_LEN 1024
|
#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,\
|
(res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
|
||||||
#x " = " fmt "\n", wl->x))
|
#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_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
|
||||||
#define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d")
|
#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_STR(x) DRIVER_STATE_PRINT(x, "%s")
|
||||||
#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
|
#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
|
||||||
#define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x")
|
#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_blocks_available);
|
||||||
DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
|
DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
|
||||||
DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
|
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(tx_blocks_freed);
|
||||||
DRIVER_STATE_PRINT_INT(rx_counter);
|
DRIVER_STATE_PRINT_INT(rx_counter);
|
||||||
DRIVER_STATE_PRINT_INT(state);
|
DRIVER_STATE_PRINT_INT(state);
|
||||||
DRIVER_STATE_PRINT_INT(channel);
|
|
||||||
DRIVER_STATE_PRINT_INT(band);
|
DRIVER_STATE_PRINT_INT(band);
|
||||||
DRIVER_STATE_PRINT_INT(power_level);
|
DRIVER_STATE_PRINT_INT(power_level);
|
||||||
DRIVER_STATE_PRINT_INT(sg_enabled);
|
DRIVER_STATE_PRINT_INT(sg_enabled);
|
||||||
|
@@ -266,6 +266,7 @@ int wl1271_event_unmask(struct wl1271 *wl)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
wl1271_debug(DEBUG_EVENT, "unmasking event_mask 0x%x", wl->event_mask);
|
||||||
ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask));
|
ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -222,6 +222,15 @@ wlcore_hw_set_peer_cap(struct wl1271 *wl,
|
|||||||
return 0;
|
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
|
static inline bool
|
||||||
wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid,
|
wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid,
|
||||||
struct wl1271_link *lnk)
|
struct wl1271_link *lnk)
|
||||||
|
@@ -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);
|
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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 */
|
/* first STA, no APs */
|
||||||
} else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) {
|
} else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) {
|
||||||
u8 sta_auth = wl->conf.conn.sta_sleep_auth;
|
u8 sta_auth = wl->conf.conn.sta_sleep_auth;
|
||||||
|
@@ -165,8 +165,8 @@ static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr,
|
|||||||
int physical;
|
int physical;
|
||||||
int addr;
|
int addr;
|
||||||
|
|
||||||
/* Addresses are stored internally as addresses to 32 bytes blocks */
|
/* Convert from FW internal address which is chip arch dependent */
|
||||||
addr = hwaddr << 5;
|
addr = wl->ops->convert_hwaddr(wl, hwaddr);
|
||||||
|
|
||||||
physical = wlcore_translate_addr(wl, addr);
|
physical = wlcore_translate_addr(wl, addr);
|
||||||
|
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#define WL1271_BOOT_RETRIES 3
|
#define WL1271_BOOT_RETRIES 3
|
||||||
|
|
||||||
static char *fwlog_param;
|
static char *fwlog_param;
|
||||||
|
static int fwlog_mem_blocks = -1;
|
||||||
static int bug_on_recovery = -1;
|
static int bug_on_recovery = -1;
|
||||||
static int no_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 */
|
/* 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 (fwlog_param) {
|
||||||
if (!strcmp(fwlog_param, "continuous")) {
|
if (!strcmp(fwlog_param, "continuous")) {
|
||||||
wl->conf.fwlog.mode = WL12XX_FWLOG_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) {
|
if (wl->state == WLCORE_STATE_ON) {
|
||||||
wl->state = WLCORE_STATE_RESTARTING;
|
wl->state = WLCORE_STATE_RESTARTING;
|
||||||
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
||||||
|
wl1271_ps_elp_wakeup(wl);
|
||||||
wlcore_disable_interrupts_nosync(wl);
|
wlcore_disable_interrupts_nosync(wl);
|
||||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
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 wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure we have enough room */
|
/* 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 */
|
/* Fill the FW log file, consumed by the sysfs fwlog entry */
|
||||||
memcpy(wl->fwlog + wl->fwlog_size, memblock, len);
|
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;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WLCORE_FW_LOG_END 0x2000000
|
|
||||||
|
|
||||||
static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
|
struct wlcore_partition_set part, old_part;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 end_of_log;
|
u32 end_of_log;
|
||||||
@@ -824,7 +828,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
|||||||
|
|
||||||
wl1271_info("Reading FW panic log");
|
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)
|
if (!block)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -850,17 +854,31 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
|||||||
|
|
||||||
if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) {
|
if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) {
|
||||||
offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor);
|
offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor);
|
||||||
end_of_log = WLCORE_FW_LOG_END;
|
end_of_log = wl->fwlog_end;
|
||||||
} else {
|
} else {
|
||||||
offset = sizeof(addr);
|
offset = sizeof(addr);
|
||||||
end_of_log = addr;
|
end_of_log = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_part = wl->curr_part;
|
||||||
|
memset(&part, 0, sizeof(part));
|
||||||
|
|
||||||
/* Traverse the memory blocks linked list */
|
/* Traverse the memory blocks linked list */
|
||||||
do {
|
do {
|
||||||
memset(block, 0, WL12XX_HW_BLOCK_SIZE);
|
part.mem.start = wlcore_hw_convert_hwaddr(wl, addr);
|
||||||
ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
|
part.mem.size = PAGE_SIZE;
|
||||||
false);
|
|
||||||
|
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)
|
if (ret < 0)
|
||||||
goto out;
|
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.
|
* on demand mode and is equal to 0x2000000 in continuous mode.
|
||||||
*/
|
*/
|
||||||
addr = le32_to_cpup((__le32 *)block);
|
addr = le32_to_cpup((__le32 *)block);
|
||||||
|
|
||||||
if (!wl12xx_copy_fwlog(wl, block + offset,
|
if (!wl12xx_copy_fwlog(wl, block + offset,
|
||||||
WL12XX_HW_BLOCK_SIZE - offset))
|
wl->fw_mem_block_size - offset))
|
||||||
break;
|
break;
|
||||||
} while (addr && (addr != end_of_log));
|
} while (addr && (addr != end_of_log));
|
||||||
|
|
||||||
@@ -880,6 +899,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(block);
|
kfree(block);
|
||||||
|
wlcore_set_partition(wl, &old_part);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wlcore_print_recovery(struct wl1271 *wl)
|
static void wlcore_print_recovery(struct wl1271 *wl)
|
||||||
@@ -924,7 +944,8 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) {
|
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);
|
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,
|
* 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));
|
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))
|
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags))
|
||||||
goto unlock;
|
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) {
|
if (wl->ap_count == 0 && is_ap && wl->sta_count) {
|
||||||
u8 sta_auth = wl->conf.conn.sta_sleep_auth;
|
u8 sta_auth = wl->conf.conn.sta_sleep_auth;
|
||||||
/* Configure for power according to debugfs */
|
/* Configure for power according to debugfs */
|
||||||
@@ -6152,6 +6181,9 @@ module_param_named(fwlog, fwlog_param, charp, 0);
|
|||||||
MODULE_PARM_DESC(fwlog,
|
MODULE_PARM_DESC(fwlog,
|
||||||
"FW logger options: continuous, ondemand, dbgpins or disable");
|
"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_param(bug_on_recovery, int, S_IRUSR | S_IWUSR);
|
||||||
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
|
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
|
||||||
|
|
||||||
|
@@ -92,9 +92,31 @@ out:
|
|||||||
static void wlcore_started_vifs_iter(void *data, u8 *mac,
|
static void wlcore_started_vifs_iter(void *data, u8 *mac,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
|
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||||
|
bool active = false;
|
||||||
int *count = (int *)data;
|
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)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -179,7 +179,8 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
|
|||||||
goto out_sleep;
|
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) {
|
if (ret < 0) {
|
||||||
wl1271_warning("testmode cmd interrogate failed: %d", ret);
|
wl1271_warning("testmode cmd interrogate failed: %d", ret);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
@@ -110,6 +110,7 @@ struct wlcore_ops {
|
|||||||
struct ieee80211_sta_ht_cap *ht_cap,
|
struct ieee80211_sta_ht_cap *ht_cap,
|
||||||
bool allow_ht_operation,
|
bool allow_ht_operation,
|
||||||
u32 rate_set, u8 hlid);
|
u32 rate_set, u8 hlid);
|
||||||
|
u32 (*convert_hwaddr)(struct wl1271 *wl, u32 hwaddr);
|
||||||
bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid,
|
bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid,
|
||||||
struct wl1271_link *lnk);
|
struct wl1271_link *lnk);
|
||||||
bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
|
bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
|
||||||
@@ -290,6 +291,12 @@ struct wl1271 {
|
|||||||
/* Number of valid bytes in the FW log buffer */
|
/* Number of valid bytes in the FW log buffer */
|
||||||
ssize_t fwlog_size;
|
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 */
|
/* Sysfs FW log entry readers wait queue */
|
||||||
wait_queue_head_t fwlog_waitq;
|
wait_queue_head_t fwlog_waitq;
|
||||||
|
|
||||||
@@ -307,6 +314,8 @@ struct wl1271 {
|
|||||||
|
|
||||||
/* The mbox event mask */
|
/* The mbox event mask */
|
||||||
u32 event_mask;
|
u32 event_mask;
|
||||||
|
/* events to unmask only when ap interface is up */
|
||||||
|
u32 ap_event_mask;
|
||||||
|
|
||||||
/* Mailbox pointers */
|
/* Mailbox pointers */
|
||||||
u32 mbox_size;
|
u32 mbox_size;
|
||||||
|
@@ -550,6 +550,4 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
|
|||||||
#define HW_HT_RATES_OFFSET 16
|
#define HW_HT_RATES_OFFSET 16
|
||||||
#define HW_MIMO_RATES_OFFSET 24
|
#define HW_MIMO_RATES_OFFSET 24
|
||||||
|
|
||||||
#define WL12XX_HW_BLOCK_SIZE 256
|
|
||||||
|
|
||||||
#endif /* __WLCORE_I_H__ */
|
#endif /* __WLCORE_I_H__ */
|
||||||
|
Reference in New Issue
Block a user