Skip to content

Commit 333c0db

Browse files
committed
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
2 parents 115f945 + 95dac04 commit 333c0db

File tree

24 files changed

+1176
-244
lines changed

24 files changed

+1176
-244
lines changed

drivers/net/wireless/wl12xx/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ config WL12XX
1111
depends on WL12XX_MENU && GENERIC_HARDIRQS
1212
depends on INET
1313
select FW_LOADER
14-
select CRC7
1514
---help---
1615
This module adds support for wireless adapters based on TI wl1271 and
1716
TI wl1273 chipsets. This module does *not* include support for wl1251.
@@ -33,6 +32,7 @@ config WL12XX_HT
3332
config WL12XX_SPI
3433
tristate "TI wl12xx SPI support"
3534
depends on WL12XX && SPI_MASTER
35+
select CRC7
3636
---help---
3737
This module adds support for the SPI interface of adapters using
3838
TI wl12xx chipsets. Select this if your platform is using

drivers/net/wireless/wl12xx/acx.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
#include <linux/module.h>
2727
#include <linux/platform_device.h>
28-
#include <linux/crc7.h>
2928
#include <linux/spi/spi.h>
3029
#include <linux/slab.h>
3130

@@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
10681067
mem_conf->tx_free_req = mem->min_req_tx_blocks;
10691068
mem_conf->rx_free_req = mem->min_req_rx_blocks;
10701069
mem_conf->tx_min = mem->tx_min;
1070+
mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;
10711071

10721072
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
10731073
sizeof(*mem_conf));
@@ -1577,6 +1577,53 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
15771577
return ret;
15781578
}
15791579

1580+
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
1581+
{
1582+
struct wl1271_acx_ps_rx_streaming *rx_streaming;
1583+
u32 conf_queues, enable_queues;
1584+
int i, ret = 0;
1585+
1586+
wl1271_debug(DEBUG_ACX, "acx ps rx streaming");
1587+
1588+
rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);
1589+
if (!rx_streaming) {
1590+
ret = -ENOMEM;
1591+
goto out;
1592+
}
1593+
1594+
conf_queues = wl->conf.rx_streaming.queues;
1595+
if (enable)
1596+
enable_queues = conf_queues;
1597+
else
1598+
enable_queues = 0;
1599+
1600+
for (i = 0; i < 8; i++) {
1601+
/*
1602+
* Skip non-changed queues, to avoid redundant acxs.
1603+
* this check assumes conf.rx_streaming.queues can't
1604+
* be changed while rx_streaming is enabled.
1605+
*/
1606+
if (!(conf_queues & BIT(i)))
1607+
continue;
1608+
1609+
rx_streaming->tid = i;
1610+
rx_streaming->enable = enable_queues & BIT(i);
1611+
rx_streaming->period = wl->conf.rx_streaming.interval;
1612+
rx_streaming->timeout = wl->conf.rx_streaming.interval;
1613+
1614+
ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
1615+
rx_streaming,
1616+
sizeof(*rx_streaming));
1617+
if (ret < 0) {
1618+
wl1271_warning("acx ps rx streaming failed: %d", ret);
1619+
goto out;
1620+
}
1621+
}
1622+
out:
1623+
kfree(rx_streaming);
1624+
return ret;
1625+
}
1626+
15801627
int wl1271_acx_max_tx_retry(struct wl1271 *wl)
15811628
{
15821629
struct wl1271_acx_max_tx_retry *acx = NULL;

drivers/net/wireless/wl12xx/acx.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {
828828
u8 tx_free_req;
829829
u8 rx_free_req;
830830
u8 tx_min;
831+
u8 fwlog_blocks;
832+
u8 padding[3];
831833
} __packed;
832834

833835
struct wl1271_acx_mem_map {
@@ -1153,6 +1155,19 @@ struct wl1271_acx_fw_tsf_information {
11531155
u8 padding[3];
11541156
} __packed;
11551157

1158+
struct wl1271_acx_ps_rx_streaming {
1159+
struct acx_header header;
1160+
1161+
u8 tid;
1162+
u8 enable;
1163+
1164+
/* interval between triggers (10-100 msec) */
1165+
u8 period;
1166+
1167+
/* timeout before first trigger (0-200 msec) */
1168+
u8 timeout;
1169+
} __packed;
1170+
11561171
struct wl1271_acx_max_tx_retry {
11571172
struct acx_header header;
11581173

@@ -1384,6 +1399,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
13841399
int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
13851400
bool enable);
13861401
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
1402+
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
13871403
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
13881404
int wl1271_acx_config_ps(struct wl1271 *wl);
13891405
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);

drivers/net/wireless/wl12xx/boot.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
102102
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
103103
}
104104

105+
static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
106+
{
107+
unsigned int quirks = 0;
108+
unsigned int *fw_ver = wl->chip.fw_ver;
109+
110+
/* Only for wl127x */
111+
if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
112+
/* Check STA version */
113+
(((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
114+
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
115+
/* Check AP version */
116+
((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
117+
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
118+
quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
119+
120+
/* Only new station firmwares support routing fw logs to the host */
121+
if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
122+
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
123+
quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
124+
125+
/* This feature is not yet supported for AP mode */
126+
if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
127+
quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
128+
129+
return quirks;
130+
}
131+
105132
static void wl1271_parse_fw_ver(struct wl1271 *wl)
106133
{
107134
int ret;
@@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
116143
memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
117144
return;
118145
}
146+
147+
/* Check if any quirks are needed with older fw versions */
148+
wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
119149
}
120150

121151
static void wl1271_boot_fw_version(struct wl1271 *wl)
@@ -749,6 +779,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
749779
clk |= (wl->ref_clock << 1) << 4;
750780
}
751781

782+
if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
783+
clk |= SCRATCH_ENABLE_LPD;
784+
752785
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
753786

754787
wl1271_set_partition(wl, &part_table[PART_WORK]);

drivers/net/wireless/wl12xx/cmd.c

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include <linux/module.h>
2525
#include <linux/platform_device.h>
26-
#include <linux/crc7.h>
2726
#include <linux/spi/spi.h>
2827
#include <linux/etherdevice.h>
2928
#include <linux/ieee80211.h>
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
106105

107106
fail:
108107
WARN_ON(1);
109-
ieee80211_queue_work(wl->hw, &wl->recovery_work);
108+
wl12xx_queue_recovery_work(wl);
110109
return ret;
111110
}
112111

@@ -135,6 +134,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
135134
/* Override the REF CLK from the NVS with the one from platform data */
136135
gen_parms->general_params.ref_clock = wl->ref_clock;
137136

137+
/* LPD mode enable (bits 6-7) in WL1271 AP mode only */
138+
if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
139+
gen_parms->general_params.general_settings |=
140+
GENERAL_SETTINGS_DRPW_LPD;
141+
138142
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
139143
if (ret < 0) {
140144
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
@@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
352356

353357
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
354358
if (ret != 0) {
355-
ieee80211_queue_work(wl->hw, &wl->recovery_work);
359+
wl12xx_queue_recovery_work(wl);
356360
return ret;
357361
}
358362

@@ -1223,3 +1227,87 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
12231227
out:
12241228
return ret;
12251229
}
1230+
1231+
int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
1232+
{
1233+
struct wl12xx_cmd_config_fwlog *cmd;
1234+
int ret = 0;
1235+
1236+
wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
1237+
1238+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1239+
if (!cmd) {
1240+
ret = -ENOMEM;
1241+
goto out;
1242+
}
1243+
1244+
cmd->logger_mode = wl->conf.fwlog.mode;
1245+
cmd->log_severity = wl->conf.fwlog.severity;
1246+
cmd->timestamp = wl->conf.fwlog.timestamp;
1247+
cmd->output = wl->conf.fwlog.output;
1248+
cmd->threshold = wl->conf.fwlog.threshold;
1249+
1250+
ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
1251+
if (ret < 0) {
1252+
wl1271_error("failed to send config firmware logger command");
1253+
goto out_free;
1254+
}
1255+
1256+
out_free:
1257+
kfree(cmd);
1258+
1259+
out:
1260+
return ret;
1261+
}
1262+
1263+
int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
1264+
{
1265+
struct wl12xx_cmd_start_fwlog *cmd;
1266+
int ret = 0;
1267+
1268+
wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
1269+
1270+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1271+
if (!cmd) {
1272+
ret = -ENOMEM;
1273+
goto out;
1274+
}
1275+
1276+
ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
1277+
if (ret < 0) {
1278+
wl1271_error("failed to send start firmware logger command");
1279+
goto out_free;
1280+
}
1281+
1282+
out_free:
1283+
kfree(cmd);
1284+
1285+
out:
1286+
return ret;
1287+
}
1288+
1289+
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
1290+
{
1291+
struct wl12xx_cmd_stop_fwlog *cmd;
1292+
int ret = 0;
1293+
1294+
wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");
1295+
1296+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1297+
if (!cmd) {
1298+
ret = -ENOMEM;
1299+
goto out;
1300+
}
1301+
1302+
ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
1303+
if (ret < 0) {
1304+
wl1271_error("failed to send stop firmware logger command");
1305+
goto out_free;
1306+
}
1307+
1308+
out_free:
1309+
kfree(cmd);
1310+
1311+
out:
1312+
return ret;
1313+
}

drivers/net/wireless/wl12xx/cmd.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ int wl1271_cmd_start_bss(struct wl1271 *wl);
7070
int wl1271_cmd_stop_bss(struct wl1271 *wl);
7171
int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
7272
int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
73+
int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
74+
int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
75+
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
7376

7477
enum wl1271_commands {
7578
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -107,6 +110,9 @@ enum wl1271_commands {
107110
CMD_START_PERIODIC_SCAN = 50,
108111
CMD_STOP_PERIODIC_SCAN = 51,
109112
CMD_SET_STA_STATE = 52,
113+
CMD_CONFIG_FWLOGGER = 53,
114+
CMD_START_FWLOGGER = 54,
115+
CMD_STOP_FWLOGGER = 55,
110116

111117
/* AP mode commands */
112118
CMD_BSS_START = 60,
@@ -575,4 +581,60 @@ struct wl1271_cmd_remove_sta {
575581
u8 padding1;
576582
} __packed;
577583

584+
/*
585+
* Continuous mode - packets are transferred to the host periodically
586+
* via the data path.
587+
* On demand - Log messages are stored in a cyclic buffer in the
588+
* firmware, and only transferred to the host when explicitly requested
589+
*/
590+
enum wl12xx_fwlogger_log_mode {
591+
WL12XX_FWLOG_CONTINUOUS,
592+
WL12XX_FWLOG_ON_DEMAND
593+
};
594+
595+
/* Include/exclude timestamps from the log messages */
596+
enum wl12xx_fwlogger_timestamp {
597+
WL12XX_FWLOG_TIMESTAMP_DISABLED,
598+
WL12XX_FWLOG_TIMESTAMP_ENABLED
599+
};
600+
601+
/*
602+
* Logs can be routed to the debug pinouts (where available), to the host bus
603+
* (SDIO/SPI), or dropped
604+
*/
605+
enum wl12xx_fwlogger_output {
606+
WL12XX_FWLOG_OUTPUT_NONE,
607+
WL12XX_FWLOG_OUTPUT_DBG_PINS,
608+
WL12XX_FWLOG_OUTPUT_HOST,
609+
};
610+
611+
struct wl12xx_cmd_config_fwlog {
612+
struct wl1271_cmd_header header;
613+
614+
/* See enum wl12xx_fwlogger_log_mode */
615+
u8 logger_mode;
616+
617+
/* Minimum log level threshold */
618+
u8 log_severity;
619+
620+
/* Include/exclude timestamps from the log messages */
621+
u8 timestamp;
622+
623+
/* See enum wl1271_fwlogger_output */
624+
u8 output;
625+
626+
/* Regulates the frequency of log messages */
627+
u8 threshold;
628+
629+
u8 padding[3];
630+
} __packed;
631+
632+
struct wl12xx_cmd_start_fwlog {
633+
struct wl1271_cmd_header header;
634+
} __packed;
635+
636+
struct wl12xx_cmd_stop_fwlog {
637+
struct wl1271_cmd_header header;
638+
} __packed;
639+
578640
#endif /* __WL1271_CMD_H__ */

0 commit comments

Comments
 (0)