diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-02-22 14:44:50 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-22 14:44:50 -0500 |
commit | 8715d941b2fa8591474e7d0dad66589fce1892d2 (patch) | |
tree | ec228ec158bb5b4424f898d336279c29de4cf81f | |
parent | ca994a36f585432458ead9133fcfe05440edbb7b (diff) | |
parent | 51c4ed95a857ded6017537fd53fa00db64908954 (diff) |
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
33 files changed, 1386 insertions, 798 deletions
diff --git a/drivers/net/wireless/wl1251/Makefile b/drivers/net/wireless/wl1251/Makefile index 58b4f935a3f6..a5c6328b5f72 100644 --- a/drivers/net/wireless/wl1251/Makefile +++ b/drivers/net/wireless/wl1251/Makefile | |||
@@ -6,3 +6,5 @@ wl1251_sdio-objs += sdio.o | |||
6 | obj-$(CONFIG_WL1251) += wl1251.o | 6 | obj-$(CONFIG_WL1251) += wl1251.o |
7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o | 7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o |
8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | 8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o |
9 | |||
10 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/wl1251/boot.c b/drivers/net/wireless/wl1251/boot.c index d729daf8e841..a2e5241382da 100644 --- a/drivers/net/wireless/wl1251/boot.c +++ b/drivers/net/wireless/wl1251/boot.c | |||
@@ -464,8 +464,6 @@ static int wl1251_boot_upload_nvs(struct wl1251 *wl) | |||
464 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | 464 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) |
465 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | 465 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); |
466 | 466 | ||
467 | val = cpu_to_le32(val); | ||
468 | |||
469 | wl1251_debug(DEBUG_BOOT, | 467 | wl1251_debug(DEBUG_BOOT, |
470 | "nvs write table 0x%x: 0x%x", | 468 | "nvs write table 0x%x: 0x%x", |
471 | nvs_start, val); | 469 | nvs_start, val); |
diff --git a/drivers/net/wireless/wl1251/io.h b/drivers/net/wireless/wl1251/io.h index c545e9d5f512..d382877c34cc 100644 --- a/drivers/net/wireless/wl1251/io.h +++ b/drivers/net/wireless/wl1251/io.h | |||
@@ -36,16 +36,15 @@ | |||
36 | 36 | ||
37 | static inline u32 wl1251_read32(struct wl1251 *wl, int addr) | 37 | static inline u32 wl1251_read32(struct wl1251 *wl, int addr) |
38 | { | 38 | { |
39 | u32 response; | 39 | wl->if_ops->read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32)); |
40 | |||
41 | wl->if_ops->read(wl, addr, &response, sizeof(u32)); | ||
42 | 40 | ||
43 | return response; | 41 | return le32_to_cpu(wl->buffer_32); |
44 | } | 42 | } |
45 | 43 | ||
46 | static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) | 44 | static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) |
47 | { | 45 | { |
48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | 46 | wl->buffer_32 = cpu_to_le32(val); |
47 | wl->if_ops->write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32)); | ||
49 | } | 48 | } |
50 | 49 | ||
51 | static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) | 50 | static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) |
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index a77f1bbbed0a..9d8f5816c6f9 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h | |||
@@ -380,7 +380,7 @@ struct wl1251 { | |||
380 | struct wl1251_stats stats; | 380 | struct wl1251_stats stats; |
381 | struct wl1251_debugfs debugfs; | 381 | struct wl1251_debugfs debugfs; |
382 | 382 | ||
383 | u32 buffer_32; | 383 | __le32 buffer_32; |
384 | u32 buffer_cmd; | 384 | u32 buffer_cmd; |
385 | u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; | 385 | u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; |
386 | struct wl1251_rx_descriptor *rx_descriptor; | 386 | struct wl1251_rx_descriptor *rx_descriptor; |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index fe67262ba19f..98f289c907a9 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -11,3 +11,5 @@ obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o | |||
11 | 11 | ||
12 | # small builtin driver bit | 12 | # small builtin driver bit |
13 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | 13 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o |
14 | |||
15 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 7537c401a448..bc96db0683a5 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -34,12 +34,14 @@ | |||
34 | #include "reg.h" | 34 | #include "reg.h" |
35 | #include "ps.h" | 35 | #include "ps.h" |
36 | 36 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
38 | u8 wake_up_event, u8 listen_interval) | ||
38 | { | 39 | { |
39 | struct acx_wake_up_condition *wake_up; | 40 | struct acx_wake_up_condition *wake_up; |
40 | int ret; | 41 | int ret; |
41 | 42 | ||
42 | wl1271_debug(DEBUG_ACX, "acx wake up conditions"); | 43 | wl1271_debug(DEBUG_ACX, "acx wake up conditions (wake_up_event %d listen_interval %d)", |
44 | wake_up_event, listen_interval); | ||
43 | 45 | ||
44 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); | 46 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); |
45 | if (!wake_up) { | 47 | if (!wake_up) { |
@@ -48,8 +50,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
48 | } | 50 | } |
49 | 51 | ||
50 | wake_up->role_id = wlvif->role_id; | 52 | wake_up->role_id = wlvif->role_id; |
51 | wake_up->wake_up_event = wl->conf.conn.wake_up_event; | 53 | wake_up->wake_up_event = wake_up_event; |
52 | wake_up->listen_interval = wl->conf.conn.listen_interval; | 54 | wake_up->listen_interval = listen_interval; |
53 | 55 | ||
54 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, | 56 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, |
55 | wake_up, sizeof(*wake_up)); | 57 | wake_up, sizeof(*wake_up)); |
@@ -1459,9 +1461,10 @@ out: | |||
1459 | return ret; | 1461 | return ret; |
1460 | } | 1462 | } |
1461 | 1463 | ||
1462 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) | 1464 | int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1465 | u64 *mactime) | ||
1463 | { | 1466 | { |
1464 | struct wl1271_acx_fw_tsf_information *tsf_info; | 1467 | struct wl12xx_acx_fw_tsf_information *tsf_info; |
1465 | int ret; | 1468 | int ret; |
1466 | 1469 | ||
1467 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); | 1470 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); |
@@ -1470,6 +1473,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) | |||
1470 | goto out; | 1473 | goto out; |
1471 | } | 1474 | } |
1472 | 1475 | ||
1476 | tsf_info->role_id = wlvif->role_id; | ||
1477 | |||
1473 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, | 1478 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, |
1474 | tsf_info, sizeof(*tsf_info)); | 1479 | tsf_info, sizeof(*tsf_info)); |
1475 | if (ret < 0) { | 1480 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 69892b40c2df..a28fc044034c 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -995,15 +995,17 @@ struct wl1271_acx_ba_receiver_setup { | |||
995 | u8 padding[2]; | 995 | u8 padding[2]; |
996 | } __packed; | 996 | } __packed; |
997 | 997 | ||
998 | struct wl1271_acx_fw_tsf_information { | 998 | struct wl12xx_acx_fw_tsf_information { |
999 | struct acx_header header; | 999 | struct acx_header header; |
1000 | 1000 | ||
1001 | u8 role_id; | ||
1002 | u8 padding1[3]; | ||
1001 | __le32 current_tsf_high; | 1003 | __le32 current_tsf_high; |
1002 | __le32 current_tsf_low; | 1004 | __le32 current_tsf_low; |
1003 | __le32 last_bttt_high; | 1005 | __le32 last_bttt_high; |
1004 | __le32 last_tbtt_low; | 1006 | __le32 last_tbtt_low; |
1005 | u8 last_dtim_count; | 1007 | u8 last_dtim_count; |
1006 | u8 padding[3]; | 1008 | u8 padding2[3]; |
1007 | } __packed; | 1009 | } __packed; |
1008 | 1010 | ||
1009 | struct wl1271_acx_ps_rx_streaming { | 1011 | struct wl1271_acx_ps_rx_streaming { |
@@ -1151,79 +1153,81 @@ struct wl12xx_acx_config_hangover { | |||
1151 | } __packed; | 1153 | } __packed; |
1152 | 1154 | ||
1153 | enum { | 1155 | enum { |
1154 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1156 | ACX_WAKE_UP_CONDITIONS = 0x0000, |
1155 | ACX_MEM_CFG = 0x0003, | 1157 | ACX_MEM_CFG = 0x0001, |
1156 | ACX_SLOT = 0x0004, | 1158 | ACX_SLOT = 0x0002, |
1157 | ACX_AC_CFG = 0x0007, | 1159 | ACX_AC_CFG = 0x0003, |
1158 | ACX_MEM_MAP = 0x0008, | 1160 | ACX_MEM_MAP = 0x0004, |
1159 | ACX_AID = 0x000A, | 1161 | ACX_AID = 0x0005, |
1160 | ACX_MEDIUM_USAGE = 0x000F, | 1162 | ACX_MEDIUM_USAGE = 0x0006, |
1161 | ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ | 1163 | ACX_STATISTICS = 0x0007, |
1162 | ACX_STATISTICS = 0x0013, /* Debug API */ | 1164 | ACX_PWR_CONSUMPTION_STATISTICS = 0x0008, |
1163 | ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, | 1165 | ACX_TID_CFG = 0x0009, |
1164 | ACX_FEATURE_CFG = 0x0015, | 1166 | ACX_PS_RX_STREAMING = 0x000A, |
1165 | ACX_TID_CFG = 0x001A, | 1167 | ACX_BEACON_FILTER_OPT = 0x000B, |
1166 | ACX_PS_RX_STREAMING = 0x001B, | 1168 | ACX_NOISE_HIST = 0x000C, |
1167 | ACX_BEACON_FILTER_OPT = 0x001F, | 1169 | ACX_HDK_VERSION = 0x000D, |
1168 | ACX_NOISE_HIST = 0x0021, | 1170 | ACX_PD_THRESHOLD = 0x000E, |
1169 | ACX_HDK_VERSION = 0x0022, /* ??? */ | 1171 | ACX_TX_CONFIG_OPT = 0x000F, |
1170 | ACX_PD_THRESHOLD = 0x0023, | 1172 | ACX_CCA_THRESHOLD = 0x0010, |
1171 | ACX_TX_CONFIG_OPT = 0x0024, | 1173 | ACX_EVENT_MBOX_MASK = 0x0011, |
1172 | ACX_CCA_THRESHOLD = 0x0025, | 1174 | ACX_CONN_MONIT_PARAMS = 0x0012, |
1173 | ACX_EVENT_MBOX_MASK = 0x0026, | 1175 | ACX_DISABLE_BROADCASTS = 0x0013, |
1174 | ACX_CONN_MONIT_PARAMS = 0x002D, | 1176 | ACX_BCN_DTIM_OPTIONS = 0x0014, |
1175 | ACX_BCN_DTIM_OPTIONS = 0x0031, | 1177 | ACX_SG_ENABLE = 0x0015, |
1176 | ACX_SG_ENABLE = 0x0032, | 1178 | ACX_SG_CFG = 0x0016, |
1177 | ACX_SG_CFG = 0x0033, | 1179 | ACX_FM_COEX_CFG = 0x0017, |
1178 | ACX_FM_COEX_CFG = 0x0034, | 1180 | ACX_BEACON_FILTER_TABLE = 0x0018, |
1179 | ACX_BEACON_FILTER_TABLE = 0x0038, | 1181 | ACX_ARP_IP_FILTER = 0x0019, |
1180 | ACX_ARP_IP_FILTER = 0x0039, | 1182 | ACX_ROAMING_STATISTICS_TBL = 0x001A, |
1181 | ACX_ROAMING_STATISTICS_TBL = 0x003B, | 1183 | ACX_RATE_POLICY = 0x001B, |
1182 | ACX_RATE_POLICY = 0x003D, | 1184 | ACX_CTS_PROTECTION = 0x001C, |
1183 | ACX_CTS_PROTECTION = 0x003E, | 1185 | ACX_SLEEP_AUTH = 0x001D, |
1184 | ACX_SLEEP_AUTH = 0x003F, | 1186 | ACX_PREAMBLE_TYPE = 0x001E, |
1185 | ACX_PREAMBLE_TYPE = 0x0040, | 1187 | ACX_ERROR_CNT = 0x001F, |
1186 | ACX_ERROR_CNT = 0x0041, | 1188 | ACX_IBSS_FILTER = 0x0020, |
1187 | ACX_IBSS_FILTER = 0x0044, | 1189 | ACX_SERVICE_PERIOD_TIMEOUT = 0x0021, |
1188 | ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, | 1190 | ACX_TSF_INFO = 0x0022, |
1189 | ACX_TSF_INFO = 0x0046, | 1191 | ACX_CONFIG_PS_WMM = 0x0023, |
1190 | ACX_CONFIG_PS_WMM = 0x0049, | 1192 | ACX_ENABLE_RX_DATA_FILTER = 0x0024, |
1191 | ACX_ENABLE_RX_DATA_FILTER = 0x004A, | 1193 | ACX_SET_RX_DATA_FILTER = 0x0025, |
1192 | ACX_SET_RX_DATA_FILTER = 0x004B, | 1194 | ACX_GET_DATA_FILTER_STATISTICS = 0x0026, |
1193 | ACX_GET_DATA_FILTER_STATISTICS = 0x004C, | 1195 | ACX_RX_CONFIG_OPT = 0x0027, |
1194 | ACX_RX_CONFIG_OPT = 0x004E, | 1196 | ACX_FRAG_CFG = 0x0028, |
1195 | ACX_FRAG_CFG = 0x004F, | 1197 | ACX_BET_ENABLE = 0x0029, |
1196 | ACX_BET_ENABLE = 0x0050, | 1198 | ACX_RSSI_SNR_TRIGGER = 0x002A, |
1197 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 1199 | ACX_RSSI_SNR_WEIGHTS = 0x002B, |
1198 | ACX_RSSI_SNR_WEIGHTS = 0x0052, | 1200 | ACX_KEEP_ALIVE_MODE = 0x002C, |
1199 | ACX_KEEP_ALIVE_MODE = 0x0053, | 1201 | ACX_SET_KEEP_ALIVE_CONFIG = 0x002D, |
1200 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1202 | ACX_BA_SESSION_INIT_POLICY = 0x002E, |
1201 | ACX_BA_SESSION_INIT_POLICY = 0x0055, | 1203 | ACX_BA_SESSION_RX_SETUP = 0x002F, |
1202 | ACX_BA_SESSION_RX_SETUP = 0x0056, | 1204 | ACX_PEER_HT_CAP = 0x0030, |
1203 | ACX_PEER_HT_CAP = 0x0057, | 1205 | ACX_HT_BSS_OPERATION = 0x0031, |
1204 | ACX_HT_BSS_OPERATION = 0x0058, | 1206 | ACX_COEX_ACTIVITY = 0x0032, |
1205 | ACX_COEX_ACTIVITY = 0x0059, | 1207 | ACX_BURST_MODE = 0x0033, |
1206 | ACX_BURST_MODE = 0x005C, | 1208 | ACX_SET_RATE_MGMT_PARAMS = 0x0034, |
1207 | ACX_SET_RATE_MGMT_PARAMS = 0x005D, | 1209 | ACX_GET_RATE_MGMT_PARAMS = 0x0035, |
1208 | ACX_SET_RATE_ADAPT_PARAMS = 0x0060, | 1210 | ACX_SET_RATE_ADAPT_PARAMS = 0x0036, |
1209 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, | 1211 | ACX_SET_DCO_ITRIM_PARAMS = 0x0037, |
1210 | ACX_GEN_FW_CMD = 0x0070, | 1212 | ACX_GEN_FW_CMD = 0x0038, |
1211 | ACX_HOST_IF_CFG_BITMAP = 0x0071, | 1213 | ACX_HOST_IF_CFG_BITMAP = 0x0039, |
1212 | ACX_MAX_TX_FAILURE = 0x0072, | 1214 | ACX_MAX_TX_FAILURE = 0x003A, |
1213 | ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073, | 1215 | ACX_UPDATE_INCONNECTION_STA_LIST = 0x003B, |
1214 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1216 | DOT11_RX_MSDU_LIFE_TIME = 0x003C, |
1215 | DOT11_CUR_TX_PWR = 0x100D, | 1217 | DOT11_CUR_TX_PWR = 0x003D, |
1216 | DOT11_RX_DOT11_MODE = 0x1012, | 1218 | DOT11_RTS_THRESHOLD = 0x003E, |
1217 | DOT11_RTS_THRESHOLD = 0x1013, | 1219 | DOT11_GROUP_ADDRESS_TBL = 0x003F, |
1218 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | 1220 | ACX_PM_CONFIG = 0x0040, |
1219 | ACX_PM_CONFIG = 0x1016, | 1221 | ACX_CONFIG_PS = 0x0041, |
1220 | ACX_CONFIG_PS = 0x1017, | 1222 | ACX_CONFIG_HANGOVER = 0x0042, |
1221 | ACX_CONFIG_HANGOVER = 0x1018, | 1223 | ACX_FEATURE_CFG = 0x0043, |
1224 | ACX_PROTECTION_CFG = 0x0044, | ||
1222 | }; | 1225 | }; |
1223 | 1226 | ||
1224 | 1227 | ||
1225 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, | 1228 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, |
1226 | struct wl12xx_vif *wlvif); | 1229 | struct wl12xx_vif *wlvif, |
1230 | u8 wake_up_event, u8 listen_interval); | ||
1227 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); | 1231 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); |
1228 | int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1232 | int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1229 | int power); | 1233 | int power); |
@@ -1296,7 +1300,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, | |||
1296 | struct wl12xx_vif *wlvif); | 1300 | struct wl12xx_vif *wlvif); |
1297 | int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, | 1301 | int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, |
1298 | u16 ssn, bool enable, u8 peer_hlid); | 1302 | u16 ssn, bool enable, u8 peer_hlid); |
1299 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1303 | int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1304 | u64 *mactime); | ||
1300 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1305 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1301 | bool enable); | 1306 | bool enable); |
1302 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 1307 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 8f9cf5a816ea..954101d03f06 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -33,65 +33,6 @@ | |||
33 | #include "event.h" | 33 | #include "event.h" |
34 | #include "rx.h" | 34 | #include "rx.h" |
35 | 35 | ||
36 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | ||
37 | [PART_DOWN] = { | ||
38 | .mem = { | ||
39 | .start = 0x00000000, | ||
40 | .size = 0x000177c0 | ||
41 | }, | ||
42 | .reg = { | ||
43 | .start = REGISTERS_BASE, | ||
44 | .size = 0x00008800 | ||
45 | }, | ||
46 | .mem2 = { | ||
47 | .start = 0x00000000, | ||
48 | .size = 0x00000000 | ||
49 | }, | ||
50 | .mem3 = { | ||
51 | .start = 0x00000000, | ||
52 | .size = 0x00000000 | ||
53 | }, | ||
54 | }, | ||
55 | |||
56 | [PART_WORK] = { | ||
57 | .mem = { | ||
58 | .start = 0x00040000, | ||
59 | .size = 0x00014fc0 | ||
60 | }, | ||
61 | .reg = { | ||
62 | .start = REGISTERS_BASE, | ||
63 | .size = 0x0000a000 | ||
64 | }, | ||
65 | .mem2 = { | ||
66 | .start = 0x003004f8, | ||
67 | .size = 0x00000004 | ||
68 | }, | ||
69 | .mem3 = { | ||
70 | .start = 0x00040404, | ||
71 | .size = 0x00000000 | ||
72 | }, | ||
73 | }, | ||
74 | |||
75 | [PART_DRPW] = { | ||
76 | .mem = { | ||
77 | .start = 0x00040000, | ||
78 | .size = 0x00014fc0 | ||
79 | }, | ||
80 | .reg = { | ||
81 | .start = DRPW_BASE, | ||
82 | .size = 0x00006000 | ||
83 | }, | ||
84 | .mem2 = { | ||
85 | .start = 0x00000000, | ||
86 | .size = 0x00000000 | ||
87 | }, | ||
88 | .mem3 = { | ||
89 | .start = 0x00000000, | ||
90 | .size = 0x00000000 | ||
91 | } | ||
92 | } | ||
93 | }; | ||
94 | |||
95 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | 36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) |
96 | { | 37 | { |
97 | u32 cpu_ctrl; | 38 | u32 cpu_ctrl; |
@@ -181,13 +122,13 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
181 | return -ENOMEM; | 122 | return -ENOMEM; |
182 | } | 123 | } |
183 | 124 | ||
184 | memcpy(&partition, &part_table[PART_DOWN], sizeof(partition)); | 125 | memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition)); |
185 | partition.mem.start = dest; | 126 | partition.mem.start = dest; |
186 | wl1271_set_partition(wl, &partition); | 127 | wl1271_set_partition(wl, &partition); |
187 | 128 | ||
188 | /* 10.1 set partition limit and chunk num */ | 129 | /* 10.1 set partition limit and chunk num */ |
189 | chunk_num = 0; | 130 | chunk_num = 0; |
190 | partition_limit = part_table[PART_DOWN].mem.size; | 131 | partition_limit = wl12xx_part_table[PART_DOWN].mem.size; |
191 | 132 | ||
192 | while (chunk_num < fw_data_len / CHUNK_SIZE) { | 133 | while (chunk_num < fw_data_len / CHUNK_SIZE) { |
193 | /* 10.2 update partition, if needed */ | 134 | /* 10.2 update partition, if needed */ |
@@ -195,7 +136,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
195 | if (addr > partition_limit) { | 136 | if (addr > partition_limit) { |
196 | addr = dest + chunk_num * CHUNK_SIZE; | 137 | addr = dest + chunk_num * CHUNK_SIZE; |
197 | partition_limit = chunk_num * CHUNK_SIZE + | 138 | partition_limit = chunk_num * CHUNK_SIZE + |
198 | part_table[PART_DOWN].mem.size; | 139 | wl12xx_part_table[PART_DOWN].mem.size; |
199 | partition.mem.start = addr; | 140 | partition.mem.start = addr; |
200 | wl1271_set_partition(wl, &partition); | 141 | wl1271_set_partition(wl, &partition); |
201 | } | 142 | } |
@@ -317,12 +258,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
317 | } | 258 | } |
318 | 259 | ||
319 | /* update current MAC address to NVS */ | 260 | /* update current MAC address to NVS */ |
320 | nvs_ptr[11] = wl->mac_addr[0]; | 261 | nvs_ptr[11] = wl->addresses[0].addr[0]; |
321 | nvs_ptr[10] = wl->mac_addr[1]; | 262 | nvs_ptr[10] = wl->addresses[0].addr[1]; |
322 | nvs_ptr[6] = wl->mac_addr[2]; | 263 | nvs_ptr[6] = wl->addresses[0].addr[2]; |
323 | nvs_ptr[5] = wl->mac_addr[3]; | 264 | nvs_ptr[5] = wl->addresses[0].addr[3]; |
324 | nvs_ptr[4] = wl->mac_addr[4]; | 265 | nvs_ptr[4] = wl->addresses[0].addr[4]; |
325 | nvs_ptr[3] = wl->mac_addr[5]; | 266 | nvs_ptr[3] = wl->addresses[0].addr[5]; |
326 | 267 | ||
327 | /* | 268 | /* |
328 | * Layout before the actual NVS tables: | 269 | * Layout before the actual NVS tables: |
@@ -383,7 +324,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
383 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | 324 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; |
384 | 325 | ||
385 | /* Now we must set the partition correctly */ | 326 | /* Now we must set the partition correctly */ |
386 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 327 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); |
387 | 328 | ||
388 | /* Copy the NVS tables to a new block to ensure alignment */ | 329 | /* Copy the NVS tables to a new block to ensure alignment */ |
389 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 330 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
@@ -492,7 +433,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
492 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); | 433 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
493 | 434 | ||
494 | /* set the working partition to its "running" mode offset */ | 435 | /* set the working partition to its "running" mode offset */ |
495 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 436 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); |
496 | 437 | ||
497 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", | 438 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", |
498 | wl->cmd_box_addr, wl->event_box_addr); | 439 | wl->cmd_box_addr, wl->event_box_addr); |
@@ -507,8 +448,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
507 | /* unmask required mbox events */ | 448 | /* unmask required mbox events */ |
508 | wl->event_mask = BSS_LOSE_EVENT_ID | | 449 | wl->event_mask = BSS_LOSE_EVENT_ID | |
509 | SCAN_COMPLETE_EVENT_ID | | 450 | SCAN_COMPLETE_EVENT_ID | |
510 | PS_REPORT_EVENT_ID | | 451 | ROLE_STOP_COMPLETE_EVENT_ID | |
511 | DISCONNECT_EVENT_COMPLETE_ID | | ||
512 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 452 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
513 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | 453 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | |
514 | SOFT_GEMINI_SENSE_EVENT_ID | | 454 | SOFT_GEMINI_SENSE_EVENT_ID | |
@@ -547,19 +487,6 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) | |||
547 | return 0; | 487 | return 0; |
548 | } | 488 | } |
549 | 489 | ||
550 | static void wl1271_boot_hw_version(struct wl1271 *wl) | ||
551 | { | ||
552 | u32 fuse; | ||
553 | |||
554 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
555 | fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | ||
556 | else | ||
557 | fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | ||
558 | fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; | ||
559 | |||
560 | wl->hw_pg_ver = (s8)fuse; | ||
561 | } | ||
562 | |||
563 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | 490 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) |
564 | { | 491 | { |
565 | u16 spare_reg; | 492 | u16 spare_reg; |
@@ -698,7 +625,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
698 | u32 pause; | 625 | u32 pause; |
699 | u32 clk; | 626 | u32 clk; |
700 | 627 | ||
701 | if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) | 628 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
702 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | 629 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; |
703 | 630 | ||
704 | if (wl->ref_clock == CONF_REF_CLK_19_2_E || | 631 | if (wl->ref_clock == CONF_REF_CLK_19_2_E || |
@@ -753,8 +680,6 @@ int wl1271_load_firmware(struct wl1271 *wl) | |||
753 | u32 tmp, clk; | 680 | u32 tmp, clk; |
754 | int selected_clock = -1; | 681 | int selected_clock = -1; |
755 | 682 | ||
756 | wl1271_boot_hw_version(wl); | ||
757 | |||
758 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 683 | if (wl->chip.id == CHIP_ID_1283_PG20) { |
759 | ret = wl128x_boot_clk(wl, &selected_clock); | 684 | ret = wl128x_boot_clk(wl, &selected_clock); |
760 | if (ret < 0) | 685 | if (ret < 0) |
@@ -769,7 +694,7 @@ int wl1271_load_firmware(struct wl1271 *wl) | |||
769 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 694 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
770 | udelay(500); | 695 | udelay(500); |
771 | 696 | ||
772 | wl1271_set_partition(wl, &part_table[PART_DRPW]); | 697 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); |
773 | 698 | ||
774 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 699 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
775 | to be used by DRPw FW. The RTRIM value will be added by the FW | 700 | to be used by DRPw FW. The RTRIM value will be added by the FW |
@@ -788,7 +713,7 @@ int wl1271_load_firmware(struct wl1271 *wl) | |||
788 | 713 | ||
789 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); | 714 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
790 | 715 | ||
791 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 716 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); |
792 | 717 | ||
793 | /* Disable interrupts */ | 718 | /* Disable interrupts */ |
794 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 719 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index 06dad9380fa7..c3adc09f403d 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h | |||
@@ -55,16 +55,6 @@ struct wl1271_static_data { | |||
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_REG_CLK_PULL 0x0cb4 | 56 | #define OCP_REG_CLK_PULL 0x0cb4 |
57 | 57 | ||
58 | #define WL127X_REG_FUSE_DATA_2_1 0x050a | ||
59 | #define WL128X_REG_FUSE_DATA_2_1 0x2152 | ||
60 | #define PG_VER_MASK 0x3c | ||
61 | #define PG_VER_OFFSET 2 | ||
62 | |||
63 | #define PG_MAJOR_VER_MASK 0x3 | ||
64 | #define PG_MAJOR_VER_OFFSET 0x0 | ||
65 | #define PG_MINOR_VER_MASK 0xc | ||
66 | #define PG_MINOR_VER_OFFSET 0x2 | ||
67 | |||
68 | #define CMD_MBOX_ADDRESS 0x407B4 | 58 | #define CMD_MBOX_ADDRESS 0x407B4 |
69 | 59 | ||
70 | #define POLARITY_LOW BIT(1) | 60 | #define POLARITY_LOW BIT(1) |
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 25990bd38be6..b776d9d5efe8 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -566,7 +566,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, | |||
566 | goto out_free; | 566 | goto out_free; |
567 | } | 567 | } |
568 | 568 | ||
569 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | 569 | ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID); |
570 | if (ret < 0) { | 570 | if (ret < 0) { |
571 | wl1271_error("cmd role stop dev event completion error"); | 571 | wl1271_error("cmd role stop dev event completion error"); |
572 | goto out_free; | 572 | goto out_free; |
@@ -715,6 +715,8 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
715 | cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); | 715 | cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); |
716 | cmd->ap.dtim_interval = bss_conf->dtim_period; | 716 | cmd->ap.dtim_interval = bss_conf->dtim_period; |
717 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | 717 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; |
718 | /* FIXME: Change when adding DFS */ | ||
719 | cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ | ||
718 | cmd->channel = wlvif->channel; | 720 | cmd->channel = wlvif->channel; |
719 | 721 | ||
720 | if (!bss_conf->hidden_ssid) { | 722 | if (!bss_conf->hidden_ssid) { |
@@ -994,7 +996,7 @@ out: | |||
994 | } | 996 | } |
995 | 997 | ||
996 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 998 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
997 | u8 ps_mode) | 999 | u8 ps_mode, u16 auto_ps_timeout) |
998 | { | 1000 | { |
999 | struct wl1271_cmd_ps_params *ps_params = NULL; | 1001 | struct wl1271_cmd_ps_params *ps_params = NULL; |
1000 | int ret = 0; | 1002 | int ret = 0; |
@@ -1009,6 +1011,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1009 | 1011 | ||
1010 | ps_params->role_id = wlvif->role_id; | 1012 | ps_params->role_id = wlvif->role_id; |
1011 | ps_params->ps_mode = ps_mode; | 1013 | ps_params->ps_mode = ps_mode; |
1014 | ps_params->auto_ps_timeout = auto_ps_timeout; | ||
1012 | 1015 | ||
1013 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 1016 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
1014 | sizeof(*ps_params), 0); | 1017 | sizeof(*ps_params), 0); |
@@ -1022,13 +1025,15 @@ out: | |||
1022 | return ret; | 1025 | return ret; |
1023 | } | 1026 | } |
1024 | 1027 | ||
1025 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 1028 | int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, |
1026 | void *buf, size_t buf_len, int index, u32 rates) | 1029 | u16 template_id, void *buf, size_t buf_len, |
1030 | int index, u32 rates) | ||
1027 | { | 1031 | { |
1028 | struct wl1271_cmd_template_set *cmd; | 1032 | struct wl1271_cmd_template_set *cmd; |
1029 | int ret = 0; | 1033 | int ret = 0; |
1030 | 1034 | ||
1031 | wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); | 1035 | wl1271_debug(DEBUG_CMD, "cmd template_set %d (role %d)", |
1036 | template_id, role_id); | ||
1032 | 1037 | ||
1033 | WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); | 1038 | WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); |
1034 | buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); | 1039 | buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); |
@@ -1039,6 +1044,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
1039 | goto out; | 1044 | goto out; |
1040 | } | 1045 | } |
1041 | 1046 | ||
1047 | /* during initialization wlvif is NULL */ | ||
1048 | cmd->role_id = role_id; | ||
1042 | cmd->len = cpu_to_le16(buf_len); | 1049 | cmd->len = cpu_to_le16(buf_len); |
1043 | cmd->template_type = template_id; | 1050 | cmd->template_type = template_id; |
1044 | cmd->enabled_rates = cpu_to_le32(rates); | 1051 | cmd->enabled_rates = cpu_to_le32(rates); |
@@ -1082,7 +1089,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1082 | ptr = skb->data; | 1089 | ptr = skb->data; |
1083 | } | 1090 | } |
1084 | 1091 | ||
1085 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, | 1092 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
1093 | CMD_TEMPL_NULL_DATA, ptr, size, 0, | ||
1086 | wlvif->basic_rate); | 1094 | wlvif->basic_rate); |
1087 | 1095 | ||
1088 | out: | 1096 | out: |
@@ -1105,7 +1113,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, | |||
1105 | if (!skb) | 1113 | if (!skb) |
1106 | goto out; | 1114 | goto out; |
1107 | 1115 | ||
1108 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, | 1116 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV, |
1109 | skb->data, skb->len, | 1117 | skb->data, skb->len, |
1110 | CMD_TEMPL_KLV_IDX_NULL_DATA, | 1118 | CMD_TEMPL_KLV_IDX_NULL_DATA, |
1111 | wlvif->basic_rate); | 1119 | wlvif->basic_rate); |
@@ -1130,7 +1138,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1130 | if (!skb) | 1138 | if (!skb) |
1131 | goto out; | 1139 | goto out; |
1132 | 1140 | ||
1133 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, | 1141 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
1142 | CMD_TEMPL_PS_POLL, skb->data, | ||
1134 | skb->len, 0, wlvif->basic_rate_set); | 1143 | skb->len, 0, wlvif->basic_rate_set); |
1135 | 1144 | ||
1136 | out: | 1145 | out: |
@@ -1138,9 +1147,10 @@ out: | |||
1138 | return ret; | 1147 | return ret; |
1139 | } | 1148 | } |
1140 | 1149 | ||
1141 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1150 | int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1151 | u8 role_id, u8 band, | ||
1142 | const u8 *ssid, size_t ssid_len, | 1152 | const u8 *ssid, size_t ssid_len, |
1143 | const u8 *ie, size_t ie_len, u8 band) | 1153 | const u8 *ie, size_t ie_len) |
1144 | { | 1154 | { |
1145 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 1155 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
1146 | struct sk_buff *skb; | 1156 | struct sk_buff *skb; |
@@ -1158,10 +1168,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1158 | 1168 | ||
1159 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); | 1169 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); |
1160 | if (band == IEEE80211_BAND_2GHZ) | 1170 | if (band == IEEE80211_BAND_2GHZ) |
1161 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 1171 | ret = wl1271_cmd_template_set(wl, role_id, |
1172 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
1162 | skb->data, skb->len, 0, rate); | 1173 | skb->data, skb->len, 0, rate); |
1163 | else | 1174 | else |
1164 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 1175 | ret = wl1271_cmd_template_set(wl, role_id, |
1176 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
1165 | skb->data, skb->len, 0, rate); | 1177 | skb->data, skb->len, 0, rate); |
1166 | 1178 | ||
1167 | out: | 1179 | out: |
@@ -1186,10 +1198,12 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | |||
1186 | 1198 | ||
1187 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); | 1199 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); |
1188 | if (wlvif->band == IEEE80211_BAND_2GHZ) | 1200 | if (wlvif->band == IEEE80211_BAND_2GHZ) |
1189 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 1201 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
1202 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
1190 | skb->data, skb->len, 0, rate); | 1203 | skb->data, skb->len, 0, rate); |
1191 | else | 1204 | else |
1192 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 1205 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
1206 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
1193 | skb->data, skb->len, 0, rate); | 1207 | skb->data, skb->len, 0, rate); |
1194 | 1208 | ||
1195 | if (ret < 0) | 1209 | if (ret < 0) |
@@ -1199,32 +1213,34 @@ out: | |||
1199 | return skb; | 1213 | return skb; |
1200 | } | 1214 | } |
1201 | 1215 | ||
1202 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1216 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
1203 | __be32 ip_addr) | ||
1204 | { | 1217 | { |
1205 | int ret; | 1218 | int ret, extra; |
1219 | u16 fc; | ||
1206 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 1220 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
1207 | struct wl12xx_arp_rsp_template tmpl; | 1221 | struct sk_buff *skb; |
1222 | struct wl12xx_arp_rsp_template *tmpl; | ||
1208 | struct ieee80211_hdr_3addr *hdr; | 1223 | struct ieee80211_hdr_3addr *hdr; |
1209 | struct arphdr *arp_hdr; | 1224 | struct arphdr *arp_hdr; |
1210 | 1225 | ||
1211 | memset(&tmpl, 0, sizeof(tmpl)); | 1226 | skb = dev_alloc_skb(sizeof(*hdr) + sizeof(__le16) + sizeof(*tmpl) + |
1227 | WL1271_EXTRA_SPACE_MAX); | ||
1228 | if (!skb) { | ||
1229 | wl1271_error("failed to allocate buffer for arp rsp template"); | ||
1230 | return -ENOMEM; | ||
1231 | } | ||
1212 | 1232 | ||
1213 | /* mac80211 header */ | 1233 | skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); |
1214 | hdr = &tmpl.hdr; | 1234 | |
1215 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | 1235 | tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); |
1216 | IEEE80211_STYPE_DATA | | 1236 | memset(tmpl, 0, sizeof(tmpl)); |
1217 | IEEE80211_FCTL_TODS); | ||
1218 | memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); | ||
1219 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); | ||
1220 | memset(hdr->addr3, 0xff, ETH_ALEN); | ||
1221 | 1237 | ||
1222 | /* llc layer */ | 1238 | /* llc layer */ |
1223 | memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); | 1239 | memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); |
1224 | tmpl.llc_type = cpu_to_be16(ETH_P_ARP); | 1240 | tmpl->llc_type = cpu_to_be16(ETH_P_ARP); |
1225 | 1241 | ||
1226 | /* arp header */ | 1242 | /* arp header */ |
1227 | arp_hdr = &tmpl.arp_hdr; | 1243 | arp_hdr = &tmpl->arp_hdr; |
1228 | arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); | 1244 | arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); |
1229 | arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); | 1245 | arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); |
1230 | arp_hdr->ar_hln = ETH_ALEN; | 1246 | arp_hdr->ar_hln = ETH_ALEN; |
@@ -1232,13 +1248,59 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1232 | arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); | 1248 | arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); |
1233 | 1249 | ||
1234 | /* arp payload */ | 1250 | /* arp payload */ |
1235 | memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN); | 1251 | memcpy(tmpl->sender_hw, vif->addr, ETH_ALEN); |
1236 | tmpl.sender_ip = ip_addr; | 1252 | tmpl->sender_ip = wlvif->ip_addr; |
1237 | 1253 | ||
1238 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, | 1254 | /* encryption space */ |
1239 | &tmpl, sizeof(tmpl), 0, | 1255 | switch (wlvif->encryption_type) { |
1240 | wlvif->basic_rate); | 1256 | case KEY_TKIP: |
1257 | extra = WL1271_EXTRA_SPACE_TKIP; | ||
1258 | break; | ||
1259 | case KEY_AES: | ||
1260 | extra = WL1271_EXTRA_SPACE_AES; | ||
1261 | break; | ||
1262 | case KEY_NONE: | ||
1263 | case KEY_WEP: | ||
1264 | case KEY_GEM: | ||
1265 | extra = 0; | ||
1266 | break; | ||
1267 | default: | ||
1268 | wl1271_warning("Unknown encryption type: %d", | ||
1269 | wlvif->encryption_type); | ||
1270 | ret = -EINVAL; | ||
1271 | goto out; | ||
1272 | } | ||
1273 | |||
1274 | if (extra) { | ||
1275 | u8 *space = skb_push(skb, extra); | ||
1276 | memset(space, 0, extra); | ||
1277 | } | ||
1278 | |||
1279 | /* QoS header - BE */ | ||
1280 | if (wlvif->sta.qos) | ||
1281 | memset(skb_push(skb, sizeof(__le16)), 0, sizeof(__le16)); | ||
1241 | 1282 | ||
1283 | /* mac80211 header */ | ||
1284 | hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); | ||
1285 | memset(hdr, 0, sizeof(hdr)); | ||
1286 | fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; | ||
1287 | if (wlvif->sta.qos) | ||
1288 | fc |= IEEE80211_STYPE_QOS_DATA; | ||
1289 | else | ||
1290 | fc |= IEEE80211_STYPE_DATA; | ||
1291 | if (wlvif->encryption_type != KEY_NONE) | ||
1292 | fc |= IEEE80211_FCTL_PROTECTED; | ||
1293 | |||
1294 | hdr->frame_control = cpu_to_le16(fc); | ||
1295 | memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); | ||
1296 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); | ||
1297 | memset(hdr->addr3, 0xff, ETH_ALEN); | ||
1298 | |||
1299 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_ARP_RSP, | ||
1300 | skb->data, skb->len, 0, | ||
1301 | wlvif->basic_rate); | ||
1302 | out: | ||
1303 | dev_kfree_skb(skb); | ||
1242 | return ret; | 1304 | return ret; |
1243 | } | 1305 | } |
1244 | 1306 | ||
@@ -1260,7 +1322,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1260 | /* FIXME: not sure what priority to use here */ | 1322 | /* FIXME: not sure what priority to use here */ |
1261 | template.qos_ctrl = cpu_to_le16(0); | 1323 | template.qos_ctrl = cpu_to_le16(0); |
1262 | 1324 | ||
1263 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | 1325 | return wl1271_cmd_template_set(wl, wlvif->role_id, |
1326 | CMD_TEMPL_QOS_NULL_DATA, &template, | ||
1264 | sizeof(template), 0, | 1327 | sizeof(template), 0, |
1265 | wlvif->basic_rate); | 1328 | wlvif->basic_rate); |
1266 | } | 1329 | } |
@@ -1744,6 +1807,7 @@ out: | |||
1744 | } | 1807 | } |
1745 | 1808 | ||
1746 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | 1809 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, |
1810 | struct wl12xx_vif *wlvif, | ||
1747 | struct ieee80211_channel_switch *ch_switch) | 1811 | struct ieee80211_channel_switch *ch_switch) |
1748 | { | 1812 | { |
1749 | struct wl12xx_cmd_channel_switch *cmd; | 1813 | struct wl12xx_cmd_channel_switch *cmd; |
@@ -1757,10 +1821,13 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl, | |||
1757 | goto out; | 1821 | goto out; |
1758 | } | 1822 | } |
1759 | 1823 | ||
1824 | cmd->role_id = wlvif->role_id; | ||
1760 | cmd->channel = ch_switch->channel->hw_value; | 1825 | cmd->channel = ch_switch->channel->hw_value; |
1761 | cmd->switch_time = ch_switch->count; | 1826 | cmd->switch_time = ch_switch->count; |
1762 | cmd->tx_suspend = ch_switch->block_tx; | 1827 | cmd->stop_tx = ch_switch->block_tx; |
1763 | cmd->flush = 0; /* this value is ignored by the FW */ | 1828 | |
1829 | /* FIXME: control from mac80211 in the future */ | ||
1830 | cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */ | ||
1764 | 1831 | ||
1765 | ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); | 1832 | ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); |
1766 | if (ret < 0) { | 1833 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 3f7d0b93c24d..de217d92516b 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h | |||
@@ -51,22 +51,23 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | |||
51 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 51 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
52 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | 52 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
53 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 53 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
54 | u8 ps_mode); | 54 | u8 ps_mode, u16 auto_ps_timeout); |
55 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 55 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
56 | size_t len); | 56 | size_t len); |
57 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 57 | int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, |
58 | void *buf, size_t buf_len, int index, u32 rates); | 58 | u16 template_id, void *buf, size_t buf_len, |
59 | int index, u32 rates); | ||
59 | int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 60 | int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
60 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 61 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
61 | u16 aid); | 62 | u16 aid); |
62 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 63 | int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
64 | u8 role_id, u8 band, | ||
63 | const u8 *ssid, size_t ssid_len, | 65 | const u8 *ssid, size_t ssid_len, |
64 | const u8 *ie, size_t ie_len, u8 band); | 66 | const u8 *ie, size_t ie_len); |
65 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | 67 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, |
66 | struct wl12xx_vif *wlvif, | 68 | struct wl12xx_vif *wlvif, |
67 | struct sk_buff *skb); | 69 | struct sk_buff *skb); |
68 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 70 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
69 | __be32 ip_addr); | ||
70 | int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); | 71 | int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); |
71 | int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, | 72 | int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, |
72 | struct wl12xx_vif *wlvif); | 73 | struct wl12xx_vif *wlvif); |
@@ -89,6 +90,7 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl); | |||
89 | int wl12xx_cmd_start_fwlog(struct wl1271 *wl); | 90 | int wl12xx_cmd_start_fwlog(struct wl1271 *wl); |
90 | int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); | 91 | int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); |
91 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, | 92 | int wl12xx_cmd_channel_switch(struct wl1271 *wl, |
93 | struct wl12xx_vif *wlvif, | ||
92 | struct ieee80211_channel_switch *ch_switch); | 94 | struct ieee80211_channel_switch *ch_switch); |
93 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); | 95 | int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); |
94 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 96 | int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -96,62 +98,65 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
96 | void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); | 98 | void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); |
97 | 99 | ||
98 | enum wl1271_commands { | 100 | enum wl1271_commands { |
99 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 101 | CMD_INTERROGATE = 1, /* use this to read information elements */ |
100 | CMD_CONFIGURE = 2, /*use this to write information elements*/ | 102 | CMD_CONFIGURE = 2, /* use this to write information elements */ |
101 | CMD_ENABLE_RX = 3, | 103 | CMD_ENABLE_RX = 3, |
102 | CMD_ENABLE_TX = 4, | 104 | CMD_ENABLE_TX = 4, |
103 | CMD_DISABLE_RX = 5, | 105 | CMD_DISABLE_RX = 5, |
104 | CMD_DISABLE_TX = 6, | 106 | CMD_DISABLE_TX = 6, |
105 | CMD_SCAN = 8, | 107 | CMD_SCAN = 7, |
106 | CMD_STOP_SCAN = 9, | 108 | CMD_STOP_SCAN = 8, |
107 | CMD_SET_KEYS = 12, | 109 | CMD_SET_KEYS = 9, |
108 | CMD_READ_MEMORY = 13, | 110 | CMD_READ_MEMORY = 10, |
109 | CMD_WRITE_MEMORY = 14, | 111 | CMD_WRITE_MEMORY = 11, |
110 | CMD_SET_TEMPLATE = 19, | 112 | CMD_SET_TEMPLATE = 12, |
111 | CMD_TEST = 23, | 113 | CMD_TEST = 13, |
112 | CMD_NOISE_HIST = 28, | 114 | CMD_NOISE_HIST = 14, |
113 | CMD_QUIET_ELEMENT_SET_STATE = 29, | 115 | CMD_QUIET_ELEMENT_SET_STATE = 15, |
114 | CMD_SET_BCN_MODE = 33, | 116 | CMD_SET_BCN_MODE = 16, |
115 | CMD_MEASUREMENT = 34, | 117 | |
116 | CMD_STOP_MEASUREMENT = 35, | 118 | CMD_MEASUREMENT = 17, |
117 | CMD_SET_PS_MODE = 37, | 119 | CMD_STOP_MEASUREMENT = 18, |
118 | CMD_CHANNEL_SWITCH = 38, | 120 | CMD_SET_PS_MODE = 19, |
119 | CMD_STOP_CHANNEL_SWICTH = 39, | 121 | CMD_CHANNEL_SWITCH = 20, |
120 | CMD_AP_DISCOVERY = 40, | 122 | CMD_STOP_CHANNEL_SWICTH = 21, |
121 | CMD_STOP_AP_DISCOVERY = 41, | 123 | CMD_AP_DISCOVERY = 22, |
122 | CMD_HEALTH_CHECK = 45, | 124 | CMD_STOP_AP_DISCOVERY = 23, |
123 | CMD_DEBUG = 46, | 125 | CMD_HEALTH_CHECK = 24, |
124 | CMD_TRIGGER_SCAN_TO = 47, | 126 | CMD_DEBUG = 25, |
125 | CMD_CONNECTION_SCAN_CFG = 48, | 127 | CMD_TRIGGER_SCAN_TO = 26, |
126 | CMD_CONNECTION_SCAN_SSID_CFG = 49, | 128 | CMD_CONNECTION_SCAN_CFG = 27, |
127 | CMD_START_PERIODIC_SCAN = 50, | 129 | CMD_CONNECTION_SCAN_SSID_CFG = 28, |
128 | CMD_STOP_PERIODIC_SCAN = 51, | 130 | CMD_START_PERIODIC_SCAN = 29, |
129 | CMD_SET_PEER_STATE = 52, | 131 | CMD_STOP_PERIODIC_SCAN = 30, |
130 | CMD_REMAIN_ON_CHANNEL = 53, | 132 | CMD_SET_PEER_STATE = 31, |
131 | CMD_CANCEL_REMAIN_ON_CHANNEL = 54, | 133 | CMD_REMAIN_ON_CHANNEL = 32, |
132 | 134 | CMD_CANCEL_REMAIN_ON_CHANNEL = 33, | |
133 | CMD_CONFIG_FWLOGGER = 55, | 135 | CMD_CONFIG_FWLOGGER = 34, |
134 | CMD_START_FWLOGGER = 56, | 136 | CMD_START_FWLOGGER = 35, |
135 | CMD_STOP_FWLOGGER = 57, | 137 | CMD_STOP_FWLOGGER = 36, |
136 | 138 | ||
137 | /* AP commands */ | 139 | /* Access point commands */ |
138 | CMD_ADD_PEER = 62, | 140 | CMD_ADD_PEER = 37, |
139 | CMD_REMOVE_PEER = 63, | 141 | CMD_REMOVE_PEER = 38, |
140 | 142 | ||
141 | /* Role API */ | 143 | /* Role API */ |
142 | CMD_ROLE_ENABLE = 70, | 144 | CMD_ROLE_ENABLE = 39, |
143 | CMD_ROLE_DISABLE = 71, | 145 | CMD_ROLE_DISABLE = 40, |
144 | CMD_ROLE_START = 72, | 146 | CMD_ROLE_START = 41, |
145 | CMD_ROLE_STOP = 73, | 147 | CMD_ROLE_STOP = 42, |
146 | 148 | ||
147 | /* WIFI Direct */ | 149 | /* DFS */ |
148 | CMD_WFD_START_DISCOVERY = 80, | 150 | CMD_START_RADAR_DETECTION = 43, |
149 | CMD_WFD_STOP_DISCOVERY = 81, | 151 | CMD_STOP_RADAR_DETECTION = 44, |
150 | CMD_WFD_ATTRIBUTE_CONFIG = 82, | ||
151 | 152 | ||
152 | CMD_NOP = 100, | 153 | /* WIFI Direct */ |
154 | CMD_WFD_START_DISCOVERY = 45, | ||
155 | CMD_WFD_STOP_DISCOVERY = 46, | ||
156 | CMD_WFD_ATTRIBUTE_CONFIG = 47, | ||
157 | CMD_NOP = 48, | ||
158 | CMD_LAST_COMMAND, | ||
153 | 159 | ||
154 | NUM_COMMANDS, | ||
155 | MAX_COMMAND_ID = 0xFFFF, | 160 | MAX_COMMAND_ID = 0xFFFF, |
156 | }; | 161 | }; |
157 | 162 | ||
@@ -191,7 +196,7 @@ enum cmd_templ { | |||
191 | /* unit ms */ | 196 | /* unit ms */ |
192 | #define WL1271_COMMAND_TIMEOUT 2000 | 197 | #define WL1271_COMMAND_TIMEOUT 2000 |
193 | #define WL1271_CMD_TEMPL_DFLT_SIZE 252 | 198 | #define WL1271_CMD_TEMPL_DFLT_SIZE 252 |
194 | #define WL1271_CMD_TEMPL_MAX_SIZE 548 | 199 | #define WL1271_CMD_TEMPL_MAX_SIZE 512 |
195 | #define WL1271_EVENT_TIMEOUT 750 | 200 | #define WL1271_EVENT_TIMEOUT 750 |
196 | 201 | ||
197 | struct wl1271_cmd_header { | 202 | struct wl1271_cmd_header { |
@@ -339,7 +344,9 @@ struct wl12xx_cmd_role_start { | |||
339 | u8 ssid_len; | 344 | u8 ssid_len; |
340 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 345 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
341 | 346 | ||
342 | u8 padding_1[5]; | 347 | u8 reset_tsf; |
348 | |||
349 | u8 padding_1[4]; | ||
343 | } __packed ap; | 350 | } __packed ap; |
344 | }; | 351 | }; |
345 | } __packed; | 352 | } __packed; |
@@ -364,14 +371,18 @@ struct cmd_enabledisable_path { | |||
364 | struct wl1271_cmd_template_set { | 371 | struct wl1271_cmd_template_set { |
365 | struct wl1271_cmd_header header; | 372 | struct wl1271_cmd_header header; |
366 | 373 | ||
367 | __le16 len; | 374 | u8 role_id; |
368 | u8 template_type; | 375 | u8 template_type; |
376 | __le16 len; | ||
369 | u8 index; /* relevant only for KLV_TEMPLATE type */ | 377 | u8 index; /* relevant only for KLV_TEMPLATE type */ |
378 | u8 padding[3]; | ||
379 | |||
370 | __le32 enabled_rates; | 380 | __le32 enabled_rates; |
371 | u8 short_retry_limit; | 381 | u8 short_retry_limit; |
372 | u8 long_retry_limit; | 382 | u8 long_retry_limit; |
373 | u8 aflags; | 383 | u8 aflags; |
374 | u8 reserved; | 384 | u8 reserved; |
385 | |||
375 | u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE]; | 386 | u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE]; |
376 | } __packed; | 387 | } __packed; |
377 | 388 | ||
@@ -388,6 +399,7 @@ struct wl1271_tim { | |||
388 | } __packed; | 399 | } __packed; |
389 | 400 | ||
390 | enum wl1271_cmd_ps_mode { | 401 | enum wl1271_cmd_ps_mode { |
402 | STATION_AUTO_PS_MODE, /* Dynamic Power Save */ | ||
391 | STATION_ACTIVE_MODE, | 403 | STATION_ACTIVE_MODE, |
392 | STATION_POWER_SAVE_MODE | 404 | STATION_POWER_SAVE_MODE |
393 | }; | 405 | }; |
@@ -397,7 +409,7 @@ struct wl1271_cmd_ps_params { | |||
397 | 409 | ||
398 | u8 role_id; | 410 | u8 role_id; |
399 | u8 ps_mode; /* STATION_* */ | 411 | u8 ps_mode; /* STATION_* */ |
400 | u8 padding[2]; | 412 | u16 auto_ps_timeout; |
401 | } __packed; | 413 | } __packed; |
402 | 414 | ||
403 | /* HW encryption keys */ | 415 | /* HW encryption keys */ |
@@ -695,14 +707,18 @@ struct wl12xx_cmd_stop_fwlog { | |||
695 | struct wl12xx_cmd_channel_switch { | 707 | struct wl12xx_cmd_channel_switch { |
696 | struct wl1271_cmd_header header; | 708 | struct wl1271_cmd_header header; |
697 | 709 | ||
710 | u8 role_id; | ||
711 | |||
698 | /* The new serving channel */ | 712 | /* The new serving channel */ |
699 | u8 channel; | 713 | u8 channel; |
700 | /* Relative time of the serving channel switch in TBTT units */ | 714 | /* Relative time of the serving channel switch in TBTT units */ |
701 | u8 switch_time; | 715 | u8 switch_time; |
702 | /* 1: Suspend TX till switch time; 0: Do not suspend TX */ | 716 | /* Stop the role TX, should expect it after radar detection */ |
703 | u8 tx_suspend; | 717 | u8 stop_tx; |
704 | /* 1: Flush TX at switch time; 0: Do not flush */ | 718 | /* The target channel tx status 1-stopped 0-open*/ |
705 | u8 flush; | 719 | u8 post_switch_tx_disable; |
720 | |||
721 | u8 padding[3]; | ||
706 | } __packed; | 722 | } __packed; |
707 | 723 | ||
708 | struct wl12xx_cmd_stop_channel_switch { | 724 | struct wl12xx_cmd_stop_channel_switch { |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 1bcfb017058d..cc50faaf03d1 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -66,7 +66,8 @@ enum { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | enum { | 68 | enum { |
69 | CONF_HW_RXTX_RATE_MCS7 = 0, | 69 | CONF_HW_RXTX_RATE_MCS7_SGI = 0, |
70 | CONF_HW_RXTX_RATE_MCS7, | ||
70 | CONF_HW_RXTX_RATE_MCS6, | 71 | CONF_HW_RXTX_RATE_MCS6, |
71 | CONF_HW_RXTX_RATE_MCS5, | 72 | CONF_HW_RXTX_RATE_MCS5, |
72 | CONF_HW_RXTX_RATE_MCS4, | 73 | CONF_HW_RXTX_RATE_MCS4, |
@@ -91,6 +92,10 @@ enum { | |||
91 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | 92 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff |
92 | }; | 93 | }; |
93 | 94 | ||
95 | /* Rates between and including these are MCS rates */ | ||
96 | #define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI | ||
97 | #define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0 | ||
98 | |||
94 | enum { | 99 | enum { |
95 | CONF_SG_DISABLE = 0, | 100 | CONF_SG_DISABLE = 0, |
96 | CONF_SG_PROTECTIVE, | 101 | CONF_SG_PROTECTIVE, |
@@ -312,6 +317,10 @@ enum { | |||
312 | CONF_AP_BT_ACL_VAL_BT_SERVE_TIME, | 317 | CONF_AP_BT_ACL_VAL_BT_SERVE_TIME, |
313 | CONF_AP_BT_ACL_VAL_WL_SERVE_TIME, | 318 | CONF_AP_BT_ACL_VAL_WL_SERVE_TIME, |
314 | 319 | ||
320 | /* CTS Diluting params */ | ||
321 | CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH, | ||
322 | CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER, | ||
323 | |||
315 | CONF_SG_TEMP_PARAM_1, | 324 | CONF_SG_TEMP_PARAM_1, |
316 | CONF_SG_TEMP_PARAM_2, | 325 | CONF_SG_TEMP_PARAM_2, |
317 | CONF_SG_TEMP_PARAM_3, | 326 | CONF_SG_TEMP_PARAM_3, |
@@ -810,6 +819,19 @@ struct conf_conn_settings { | |||
810 | u8 listen_interval; | 819 | u8 listen_interval; |
811 | 820 | ||
812 | /* | 821 | /* |
822 | * Firmware wakeup conditions during suspend | ||
823 | * Range: CONF_WAKE_UP_EVENT_* | ||
824 | */ | ||
825 | u8 suspend_wake_up_event; | ||
826 | |||
827 | /* | ||
828 | * Listen interval during suspend. | ||
829 | * Currently will be in DTIMs (1-10) | ||
830 | * | ||
831 | */ | ||
832 | u8 suspend_listen_interval; | ||
833 | |||
834 | /* | ||
813 | * Enable or disable the beacon filtering. | 835 | * Enable or disable the beacon filtering. |
814 | * | 836 | * |
815 | * Range: CONF_BCN_FILT_MODE_* | 837 | * Range: CONF_BCN_FILT_MODE_* |
@@ -868,13 +890,6 @@ struct conf_conn_settings { | |||
868 | u8 ps_poll_threshold; | 890 | u8 ps_poll_threshold; |
869 | 891 | ||
870 | /* | 892 | /* |
871 | * PS Poll failure recovery ACTIVE period length | ||
872 | * | ||
873 | * Range: u32 (ms) | ||
874 | */ | ||
875 | u32 ps_poll_recovery_period; | ||
876 | |||
877 | /* | ||
878 | * Configuration of signal average weights. | 893 | * Configuration of signal average weights. |
879 | */ | 894 | */ |
880 | struct conf_sig_weights sig_weights; | 895 | struct conf_sig_weights sig_weights; |
@@ -922,6 +937,18 @@ struct conf_conn_settings { | |||
922 | u8 psm_entry_nullfunc_retries; | 937 | u8 psm_entry_nullfunc_retries; |
923 | 938 | ||
924 | /* | 939 | /* |
940 | * Specifies the dynamic PS timeout in ms that will be used | ||
941 | * by the FW when in AUTO_PS mode | ||
942 | */ | ||
943 | u16 dynamic_ps_timeout; | ||
944 | |||
945 | /* | ||
946 | * Specifies whether dynamic PS should be disabled and PSM forced. | ||
947 | * This is required for certain WiFi certification tests. | ||
948 | */ | ||
949 | u8 forced_ps; | ||
950 | |||
951 | /* | ||
925 | * | 952 | * |
926 | * Specifies the interval of the connection keep-alive null-func | 953 | * Specifies the interval of the connection keep-alive null-func |
927 | * frame in ms. | 954 | * frame in ms. |
@@ -1055,6 +1082,14 @@ struct conf_scan_settings { | |||
1055 | */ | 1082 | */ |
1056 | u16 num_probe_reqs; | 1083 | u16 num_probe_reqs; |
1057 | 1084 | ||
1085 | /* | ||
1086 | * Scan trigger (split scan) timeout. The FW will split the scan | ||
1087 | * operation into slices of the given time and allow the FW to schedule | ||
1088 | * other tasks in between. | ||
1089 | * | ||
1090 | * Range: u32 Microsecs | ||
1091 | */ | ||
1092 | u32 split_scan_timeout; | ||
1058 | }; | 1093 | }; |
1059 | 1094 | ||
1060 | struct conf_sched_scan_settings { | 1095 | struct conf_sched_scan_settings { |
diff --git a/drivers/net/wireless/wl12xx/debug.h b/drivers/net/wireless/wl12xx/debug.h index b85fd8c41e8f..ec0fdc25b280 100644 --- a/drivers/net/wireless/wl12xx/debug.h +++ b/drivers/net/wireless/wl12xx/debug.h | |||
@@ -51,6 +51,7 @@ enum { | |||
51 | DEBUG_FILTERS = BIT(15), | 51 | DEBUG_FILTERS = BIT(15), |
52 | DEBUG_ADHOC = BIT(16), | 52 | DEBUG_ADHOC = BIT(16), |
53 | DEBUG_AP = BIT(17), | 53 | DEBUG_AP = BIT(17), |
54 | DEBUG_PROBE = BIT(18), | ||
54 | DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), | 55 | DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), |
55 | DEBUG_ALL = ~0, | 56 | DEBUG_ALL = ~0, |
56 | }; | 57 | }; |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 15eb3a9c30ca..e1cf72765965 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) | |||
113 | if (ret < 0) | 113 | if (ret < 0) |
114 | goto out; | 114 | goto out; |
115 | 115 | ||
116 | if (wl->state == WL1271_STATE_ON && | 116 | if (wl->state == WL1271_STATE_ON && !wl->plt && |
117 | time_after(jiffies, wl->stats.fw_stats_update + | 117 | time_after(jiffies, wl->stats.fw_stats_update + |
118 | msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { | 118 | msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { |
119 | wl1271_acx_statistics(wl, wl->stats.fw_stats); | 119 | wl1271_acx_statistics(wl, wl->stats.fw_stats); |
@@ -312,6 +312,181 @@ static const struct file_operations start_recovery_ops = { | |||
312 | .llseek = default_llseek, | 312 | .llseek = default_llseek, |
313 | }; | 313 | }; |
314 | 314 | ||
315 | static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf, | ||
316 | size_t count, loff_t *ppos) | ||
317 | { | ||
318 | struct wl1271 *wl = file->private_data; | ||
319 | |||
320 | return wl1271_format_buffer(user_buf, count, | ||
321 | ppos, "%d\n", | ||
322 | wl->conf.conn.dynamic_ps_timeout); | ||
323 | } | ||
324 | |||
325 | static ssize_t dynamic_ps_timeout_write(struct file *file, | ||
326 | const char __user *user_buf, | ||
327 | size_t count, loff_t *ppos) | ||
328 | { | ||
329 | struct wl1271 *wl = file->private_data; | ||
330 | struct wl12xx_vif *wlvif; | ||
331 | unsigned long value; | ||
332 | int ret; | ||
333 | |||
334 | ret = kstrtoul_from_user(user_buf, count, 10, &value); | ||
335 | if (ret < 0) { | ||
336 | wl1271_warning("illegal value in dynamic_ps"); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | if (value < 1 || value > 65535) { | ||
341 | wl1271_warning("dyanmic_ps_timeout is not in valid range"); | ||
342 | return -ERANGE; | ||
343 | } | ||
344 | |||
345 | mutex_lock(&wl->mutex); | ||
346 | |||
347 | wl->conf.conn.dynamic_ps_timeout = value; | ||
348 | |||
349 | if (wl->state == WL1271_STATE_OFF) | ||
350 | goto out; | ||
351 | |||
352 | ret = wl1271_ps_elp_wakeup(wl); | ||
353 | if (ret < 0) | ||
354 | goto out; | ||
355 | |||
356 | /* In case we're already in PSM, trigger it again to set new timeout | ||
357 | * immediately without waiting for re-association | ||
358 | */ | ||
359 | |||
360 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
361 | if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) | ||
362 | wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); | ||
363 | } | ||
364 | |||
365 | wl1271_ps_elp_sleep(wl); | ||
366 | |||
367 | out: | ||
368 | mutex_unlock(&wl->mutex); | ||
369 | return count; | ||
370 | } | ||
371 | |||
372 | static const struct file_operations dynamic_ps_timeout_ops = { | ||
373 | .read = dynamic_ps_timeout_read, | ||
374 | .write = dynamic_ps_timeout_write, | ||
375 | .open = wl1271_open_file_generic, | ||
376 | .llseek = default_llseek, | ||
377 | }; | ||
378 | |||
379 | static ssize_t forced_ps_read(struct file *file, char __user *user_buf, | ||
380 | size_t count, loff_t *ppos) | ||
381 | { | ||
382 | struct wl1271 *wl = file->private_data; | ||
383 | |||
384 | return wl1271_format_buffer(user_buf, count, | ||
385 | ppos, "%d\n", | ||
386 | wl->conf.conn.forced_ps); | ||
387 | } | ||
388 | |||
389 | static ssize_t forced_ps_write(struct file *file, | ||
390 | const char __user *user_buf, | ||
391 | size_t count, loff_t *ppos) | ||
392 | { | ||
393 | struct wl1271 *wl = file->private_data; | ||
394 | struct wl12xx_vif *wlvif; | ||
395 | unsigned long value; | ||
396 | int ret, ps_mode; | ||
397 | |||
398 | ret = kstrtoul_from_user(user_buf, count, 10, &value); | ||
399 | if (ret < 0) { | ||
400 | wl1271_warning("illegal value in forced_ps"); | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | if (value != 1 && value != 0) { | ||
405 | wl1271_warning("forced_ps should be either 0 or 1"); | ||
406 | return -ERANGE; | ||
407 | } | ||
408 | |||
409 | mutex_lock(&wl->mutex); | ||
410 | |||
411 | if (wl->conf.conn.forced_ps == value) | ||
412 | goto out; | ||
413 | |||
414 | wl->conf.conn.forced_ps = value; | ||
415 | |||
416 | if (wl->state == WL1271_STATE_OFF) | ||
417 | goto out; | ||
418 | |||
419 | ret = wl1271_ps_elp_wakeup(wl); | ||
420 | if (ret < 0) | ||
421 | goto out; | ||
422 | |||
423 | /* In case we're already in PSM, trigger it again to switch mode | ||
424 | * immediately without waiting for re-association | ||
425 | */ | ||
426 | |||
427 | ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE; | ||
428 | |||
429 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
430 | if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) | ||
431 | wl1271_ps_set_mode(wl, wlvif, ps_mode); | ||
432 | } | ||
433 | |||
434 | wl1271_ps_elp_sleep(wl); | ||
435 | |||
436 | out: | ||
437 | mutex_unlock(&wl->mutex); | ||
438 | return count; | ||
439 | } | ||
440 | |||
441 | static const struct file_operations forced_ps_ops = { | ||
442 | .read = forced_ps_read, | ||
443 | .write = forced_ps_write, | ||
444 | .open = wl1271_open_file_generic, | ||
445 | .llseek = default_llseek, | ||
446 | }; | ||
447 | |||
448 | static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf, | ||
449 | size_t count, loff_t *ppos) | ||
450 | { | ||
451 | struct wl1271 *wl = file->private_data; | ||
452 | |||
453 | return wl1271_format_buffer(user_buf, count, | ||
454 | ppos, "%d\n", | ||
455 | wl->conf.scan.split_scan_timeout / 1000); | ||
456 | } | ||
457 | |||
458 | static ssize_t split_scan_timeout_write(struct file *file, | ||
459 | const char __user *user_buf, | ||
460 | size_t count, loff_t *ppos) | ||
461 | { | ||
462 | struct wl1271 *wl = file->private_data; | ||
463 | unsigned long value; | ||
464 | int ret; | ||
465 | |||
466 | ret = kstrtoul_from_user(user_buf, count, 10, &value); | ||
467 | if (ret < 0) { | ||
468 | wl1271_warning("illegal value in split_scan_timeout"); | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | if (value == 0) | ||
473 | wl1271_info("split scan will be disabled"); | ||
474 | |||
475 | mutex_lock(&wl->mutex); | ||
476 | |||
477 | wl->conf.scan.split_scan_timeout = value * 1000; | ||
478 | |||
479 | mutex_unlock(&wl->mutex); | ||
480 | return count; | ||
481 | } | ||
482 | |||
483 | static const struct file_operations split_scan_timeout_ops = { | ||
484 | .read = split_scan_timeout_read, | ||
485 | .write = split_scan_timeout_write, | ||
486 | .open = wl1271_open_file_generic, | ||
487 | .llseek = default_llseek, | ||
488 | }; | ||
489 | |||
315 | static ssize_t driver_state_read(struct file *file, char __user *user_buf, | 490 | static ssize_t driver_state_read(struct file *file, char __user *user_buf, |
316 | size_t count, loff_t *ppos) | 491 | size_t count, loff_t *ppos) |
317 | { | 492 | { |
@@ -446,6 +621,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
446 | VIF_STATE_PRINT_INT(sta.basic_rate_idx); | 621 | VIF_STATE_PRINT_INT(sta.basic_rate_idx); |
447 | VIF_STATE_PRINT_INT(sta.ap_rate_idx); | 622 | VIF_STATE_PRINT_INT(sta.ap_rate_idx); |
448 | VIF_STATE_PRINT_INT(sta.p2p_rate_idx); | 623 | VIF_STATE_PRINT_INT(sta.p2p_rate_idx); |
624 | VIF_STATE_PRINT_INT(sta.qos); | ||
449 | } else { | 625 | } else { |
450 | VIF_STATE_PRINT_INT(ap.global_hlid); | 626 | VIF_STATE_PRINT_INT(ap.global_hlid); |
451 | VIF_STATE_PRINT_INT(ap.bcast_hlid); | 627 | VIF_STATE_PRINT_INT(ap.bcast_hlid); |
@@ -471,7 +647,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
471 | VIF_STATE_PRINT_INT(default_key); | 647 | VIF_STATE_PRINT_INT(default_key); |
472 | VIF_STATE_PRINT_INT(aid); | 648 | VIF_STATE_PRINT_INT(aid); |
473 | VIF_STATE_PRINT_INT(session_counter); | 649 | VIF_STATE_PRINT_INT(session_counter); |
474 | VIF_STATE_PRINT_INT(ps_poll_failures); | ||
475 | VIF_STATE_PRINT_INT(psm_entry_retry); | 650 | VIF_STATE_PRINT_INT(psm_entry_retry); |
476 | VIF_STATE_PRINT_INT(power_level); | 651 | VIF_STATE_PRINT_INT(power_level); |
477 | VIF_STATE_PRINT_INT(rssi_thold); | 652 | VIF_STATE_PRINT_INT(rssi_thold); |
@@ -562,6 +737,64 @@ static const struct file_operations dtim_interval_ops = { | |||
562 | .llseek = default_llseek, | 737 | .llseek = default_llseek, |
563 | }; | 738 | }; |
564 | 739 | ||
740 | |||
741 | |||
742 | static ssize_t suspend_dtim_interval_read(struct file *file, | ||
743 | char __user *user_buf, | ||
744 | size_t count, loff_t *ppos) | ||
745 | { | ||
746 | struct wl1271 *wl = file->private_data; | ||
747 | u8 value; | ||
748 | |||
749 | if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM || | ||
750 | wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) | ||
751 | value = wl->conf.conn.suspend_listen_interval; | ||
752 | else | ||
753 | value = 0; | ||
754 | |||
755 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
756 | } | ||
757 | |||
758 | static ssize_t suspend_dtim_interval_write(struct file *file, | ||
759 | const char __user *user_buf, | ||
760 | size_t count, loff_t *ppos) | ||
761 | { | ||
762 | struct wl1271 *wl = file->private_data; | ||
763 | unsigned long value; | ||
764 | int ret; | ||
765 | |||
766 | ret = kstrtoul_from_user(user_buf, count, 10, &value); | ||
767 | if (ret < 0) { | ||
768 | wl1271_warning("illegal value for suspend_dtim_interval"); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | if (value < 1 || value > 10) { | ||
773 | wl1271_warning("suspend_dtim value is not in valid range"); | ||
774 | return -ERANGE; | ||
775 | } | ||
776 | |||
777 | mutex_lock(&wl->mutex); | ||
778 | |||
779 | wl->conf.conn.suspend_listen_interval = value; | ||
780 | /* for some reason there are different event types for 1 and >1 */ | ||
781 | if (value == 1) | ||
782 | wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM; | ||
783 | else | ||
784 | wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; | ||
785 | |||
786 | mutex_unlock(&wl->mutex); | ||
787 | return count; | ||
788 | } | ||
789 | |||
790 | |||
791 | static const struct file_operations suspend_dtim_interval_ops = { | ||
792 | .read = suspend_dtim_interval_read, | ||
793 | .write = suspend_dtim_interval_write, | ||
794 | .open = wl1271_open_file_generic, | ||
795 | .llseek = default_llseek, | ||
796 | }; | ||
797 | |||
565 | static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, | 798 | static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, |
566 | size_t count, loff_t *ppos) | 799 | size_t count, loff_t *ppos) |
567 | { | 800 | { |
@@ -886,8 +1119,12 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
886 | DEBUGFS_ADD(driver_state, rootdir); | 1119 | DEBUGFS_ADD(driver_state, rootdir); |
887 | DEBUGFS_ADD(vifs_state, rootdir); | 1120 | DEBUGFS_ADD(vifs_state, rootdir); |
888 | DEBUGFS_ADD(dtim_interval, rootdir); | 1121 | DEBUGFS_ADD(dtim_interval, rootdir); |
1122 | DEBUGFS_ADD(suspend_dtim_interval, rootdir); | ||
889 | DEBUGFS_ADD(beacon_interval, rootdir); | 1123 | DEBUGFS_ADD(beacon_interval, rootdir); |
890 | DEBUGFS_ADD(beacon_filtering, rootdir); | 1124 | DEBUGFS_ADD(beacon_filtering, rootdir); |
1125 | DEBUGFS_ADD(dynamic_ps_timeout, rootdir); | ||
1126 | DEBUGFS_ADD(forced_ps, rootdir); | ||
1127 | DEBUGFS_ADD(split_scan_timeout, rootdir); | ||
891 | 1128 | ||
892 | streaming = debugfs_create_dir("rx_streaming", rootdir); | 1129 | streaming = debugfs_create_dir("rx_streaming", rootdir); |
893 | if (!streaming || IS_ERR(streaming)) | 1130 | if (!streaming || IS_ERR(streaming)) |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d3280df68f5d..c953717f38eb 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -30,133 +30,6 @@ | |||
30 | #include "scan.h" | 30 | #include "scan.h" |
31 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
32 | 32 | ||
33 | void wl1271_pspoll_work(struct work_struct *work) | ||
34 | { | ||
35 | struct ieee80211_vif *vif; | ||
36 | struct wl12xx_vif *wlvif; | ||
37 | struct delayed_work *dwork; | ||
38 | struct wl1271 *wl; | ||
39 | int ret; | ||
40 | |||
41 | dwork = container_of(work, struct delayed_work, work); | ||
42 | wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work); | ||
43 | vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv); | ||
44 | wl = wlvif->wl; | ||
45 | |||
46 | wl1271_debug(DEBUG_EVENT, "pspoll work"); | ||
47 | |||
48 | mutex_lock(&wl->mutex); | ||
49 | |||
50 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
51 | goto out; | ||
52 | |||
53 | if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags)) | ||
54 | goto out; | ||
55 | |||
56 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
57 | goto out; | ||
58 | |||
59 | /* | ||
60 | * if we end up here, then we were in powersave when the pspoll | ||
61 | * delivery failure occurred, and no-one changed state since, so | ||
62 | * we should go back to powersave. | ||
63 | */ | ||
64 | ret = wl1271_ps_elp_wakeup(wl); | ||
65 | if (ret < 0) | ||
66 | goto out; | ||
67 | |||
68 | wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, | ||
69 | wlvif->basic_rate, true); | ||
70 | |||
71 | wl1271_ps_elp_sleep(wl); | ||
72 | out: | ||
73 | mutex_unlock(&wl->mutex); | ||
74 | }; | ||
75 | |||
76 | static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, | ||
77 | struct wl12xx_vif *wlvif) | ||
78 | { | ||
79 | int delay = wl->conf.conn.ps_poll_recovery_period; | ||
80 | int ret; | ||
81 | |||
82 | wlvif->ps_poll_failures++; | ||
83 | if (wlvif->ps_poll_failures == 1) | ||
84 | wl1271_info("AP with dysfunctional ps-poll, " | ||
85 | "trying to work around it."); | ||
86 | |||
87 | /* force active mode receive data from the AP */ | ||
88 | if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | ||
89 | ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, | ||
90 | wlvif->basic_rate, true); | ||
91 | if (ret < 0) | ||
92 | return; | ||
93 | set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); | ||
94 | ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, | ||
95 | msecs_to_jiffies(delay)); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * If already in active mode, lets we should be getting data from | ||
100 | * the AP right away. If we enter PSM too fast after this, and data | ||
101 | * remains on the AP, we will get another event like this, and we'll | ||
102 | * go into active once more. | ||
103 | */ | ||
104 | } | ||
105 | |||
106 | static int wl1271_event_ps_report(struct wl1271 *wl, | ||
107 | struct wl12xx_vif *wlvif, | ||
108 | struct event_mailbox *mbox, | ||
109 | bool *beacon_loss) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | u32 total_retries = wl->conf.conn.psm_entry_retries; | ||
113 | |||
114 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); | ||
115 | |||
116 | switch (mbox->ps_status) { | ||
117 | case EVENT_ENTER_POWER_SAVE_FAIL: | ||
118 | wl1271_debug(DEBUG_PSM, "PSM entry failed"); | ||
119 | |||
120 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | ||
121 | /* remain in active mode */ | ||
122 | wlvif->psm_entry_retry = 0; | ||
123 | break; | ||
124 | } | ||
125 | |||
126 | if (wlvif->psm_entry_retry < total_retries) { | ||
127 | wlvif->psm_entry_retry++; | ||
128 | ret = wl1271_ps_set_mode(wl, wlvif, | ||
129 | STATION_POWER_SAVE_MODE, | ||
130 | wlvif->basic_rate, true); | ||
131 | } else { | ||
132 | wl1271_info("No ack to nullfunc from AP."); | ||
133 | wlvif->psm_entry_retry = 0; | ||
134 | *beacon_loss = true; | ||
135 | } | ||
136 | break; | ||
137 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | ||
138 | wlvif->psm_entry_retry = 0; | ||
139 | |||
140 | /* | ||
141 | * BET has only a minor effect in 5GHz and masks | ||
142 | * channel switch IEs, so we only enable BET on 2.4GHz | ||
143 | */ | ||
144 | if (wlvif->band == IEEE80211_BAND_2GHZ) | ||
145 | /* enable beacon early termination */ | ||
146 | ret = wl1271_acx_bet_enable(wl, wlvif, true); | ||
147 | |||
148 | if (wlvif->ps_compl) { | ||
149 | complete(wlvif->ps_compl); | ||
150 | wlvif->ps_compl = NULL; | ||
151 | } | ||
152 | break; | ||
153 | default: | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | 33 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, |
161 | struct wl12xx_vif *wlvif, | 34 | struct wl12xx_vif *wlvif, |
162 | struct event_mailbox *mbox) | 35 | struct event_mailbox *mbox) |
@@ -205,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
205 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | 78 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, |
206 | u8 enable) | 79 | u8 enable) |
207 | { | 80 | { |
208 | struct ieee80211_vif *vif; | ||
209 | struct wl12xx_vif *wlvif; | 81 | struct wl12xx_vif *wlvif; |
210 | 82 | ||
211 | if (enable) { | 83 | if (enable) { |
212 | /* disable dynamic PS when requested by the firmware */ | ||
213 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
214 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
215 | ieee80211_disable_dyn_ps(vif); | ||
216 | } | ||
217 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | 84 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); |
218 | } else { | 85 | } else { |
219 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | 86 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); |
220 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 87 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
221 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
222 | ieee80211_enable_dyn_ps(vif); | ||
223 | wl1271_recalc_rx_streaming(wl, wlvif); | 88 | wl1271_recalc_rx_streaming(wl, wlvif); |
224 | } | 89 | } |
225 | } | 90 | } |
@@ -237,7 +102,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
237 | { | 102 | { |
238 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
239 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
240 | int ret; | ||
241 | u32 vector; | 105 | u32 vector; |
242 | bool beacon_loss = false; | 106 | bool beacon_loss = false; |
243 | bool disconnect_sta = false; | 107 | bool disconnect_sta = false; |
@@ -293,21 +157,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
293 | beacon_loss = true; | 157 | beacon_loss = true; |
294 | } | 158 | } |
295 | 159 | ||
296 | if (vector & PS_REPORT_EVENT_ID) { | ||
297 | wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); | ||
298 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
299 | ret = wl1271_event_ps_report(wl, wlvif, | ||
300 | mbox, &beacon_loss); | ||
301 | if (ret < 0) | ||
302 | return ret; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) | ||
307 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
308 | wl1271_event_pspoll_delivery_fail(wl, wlvif); | ||
309 | } | ||
310 | |||
311 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 160 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
312 | /* TODO: check actual multi-role support */ | 161 | /* TODO: check actual multi-role support */ |
313 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); | 162 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
@@ -344,7 +193,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
344 | 193 | ||
345 | /* TODO: configure only the relevant vif */ | 194 | /* TODO: configure only the relevant vif */ |
346 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 195 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
347 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
348 | bool success; | 196 | bool success; |
349 | 197 | ||
350 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, | 198 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, |
@@ -352,6 +200,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
352 | continue; | 200 | continue; |
353 | 201 | ||
354 | success = mbox->channel_switch_status ? false : true; | 202 | success = mbox->channel_switch_status ? false : true; |
203 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
204 | |||
355 | ieee80211_chswitch_done(vif, success); | 205 | ieee80211_chswitch_done(vif, success); |
356 | } | 206 | } |
357 | } | 207 | } |
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 1d878ba47bf4..057d193d3525 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h | |||
@@ -51,10 +51,10 @@ enum { | |||
51 | SCAN_COMPLETE_EVENT_ID = BIT(10), | 51 | SCAN_COMPLETE_EVENT_ID = BIT(10), |
52 | WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), | 52 | WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), |
53 | AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), | 53 | AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), |
54 | PS_REPORT_EVENT_ID = BIT(13), | 54 | RESERVED1 = BIT(13), |
55 | PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), | 55 | PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), |
56 | DISCONNECT_EVENT_COMPLETE_ID = BIT(15), | 56 | ROLE_STOP_COMPLETE_EVENT_ID = BIT(15), |
57 | /* BIT(16) is reserved */ | 57 | RADAR_DETECTED_EVENT_ID = BIT(16), |
58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | 58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), |
59 | BSS_LOSE_EVENT_ID = BIT(18), | 59 | BSS_LOSE_EVENT_ID = BIT(18), |
60 | REGAINED_BSS_EVENT_ID = BIT(19), | 60 | REGAINED_BSS_EVENT_ID = BIT(19), |
@@ -94,9 +94,9 @@ struct event_mailbox { | |||
94 | u8 soft_gemini_sense_info; | 94 | u8 soft_gemini_sense_info; |
95 | u8 soft_gemini_protective_info; | 95 | u8 soft_gemini_protective_info; |
96 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; | 96 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; |
97 | u8 channel_switch_status; | 97 | u8 change_auto_mode_timeout; |
98 | u8 scheduled_scan_status; | 98 | u8 scheduled_scan_status; |
99 | u8 ps_status; | 99 | u8 reserved4; |
100 | /* tuned channel (roc) */ | 100 | /* tuned channel (roc) */ |
101 | u8 roc_channel; | 101 | u8 roc_channel; |
102 | 102 | ||
@@ -119,17 +119,21 @@ struct event_mailbox { | |||
119 | u8 rx_ba_allowed; | 119 | u8 rx_ba_allowed; |
120 | u8 reserved_6[2]; | 120 | u8 reserved_6[2]; |
121 | 121 | ||
122 | /* Channel switch results */ | ||
123 | |||
124 | u8 channel_switch_role_id; | ||
125 | u8 channel_switch_status; | ||
126 | u8 reserved_7[2]; | ||
127 | |||
122 | u8 ps_poll_delivery_failure_role_ids; | 128 | u8 ps_poll_delivery_failure_role_ids; |
123 | u8 stopped_role_ids; | 129 | u8 stopped_role_ids; |
124 | u8 started_role_ids; | 130 | u8 started_role_ids; |
125 | u8 change_auto_mode_timeout; | ||
126 | 131 | ||
127 | u8 reserved_7[12]; | 132 | u8 reserved_8[9]; |
128 | } __packed; | 133 | } __packed; |
129 | 134 | ||
130 | int wl1271_event_unmask(struct wl1271 *wl); | 135 | int wl1271_event_unmask(struct wl1271 *wl); |
131 | void wl1271_event_mbox_config(struct wl1271 *wl); | 136 | void wl1271_event_mbox_config(struct wl1271 *wl); |
132 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 137 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
133 | void wl1271_pspoll_work(struct work_struct *work); | ||
134 | 138 | ||
135 | #endif | 139 | #endif |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ca7ee59e4505..203fbebf09eb 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -37,54 +37,64 @@ | |||
37 | int wl1271_init_templates_config(struct wl1271 *wl) | 37 | int wl1271_init_templates_config(struct wl1271 *wl) |
38 | { | 38 | { |
39 | int ret, i; | 39 | int ret, i; |
40 | size_t max_size; | ||
40 | 41 | ||
41 | /* send empty templates for fw memory reservation */ | 42 | /* send empty templates for fw memory reservation */ |
42 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 43 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
43 | WL1271_CMD_TEMPL_DFLT_SIZE, | 44 | CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
45 | WL1271_CMD_TEMPL_MAX_SIZE, | ||
44 | 0, WL1271_RATE_AUTOMATIC); | 46 | 0, WL1271_RATE_AUTOMATIC); |
45 | if (ret < 0) | 47 | if (ret < 0) |
46 | return ret; | 48 | return ret; |
47 | 49 | ||
48 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 50 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
49 | NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, | 51 | CMD_TEMPL_CFG_PROBE_REQ_5, |
52 | NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, | ||
50 | WL1271_RATE_AUTOMATIC); | 53 | WL1271_RATE_AUTOMATIC); |
51 | if (ret < 0) | 54 | if (ret < 0) |
52 | return ret; | 55 | return ret; |
53 | 56 | ||
54 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 57 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
58 | CMD_TEMPL_NULL_DATA, NULL, | ||
55 | sizeof(struct wl12xx_null_data_template), | 59 | sizeof(struct wl12xx_null_data_template), |
56 | 0, WL1271_RATE_AUTOMATIC); | 60 | 0, WL1271_RATE_AUTOMATIC); |
57 | if (ret < 0) | 61 | if (ret < 0) |
58 | return ret; | 62 | return ret; |
59 | 63 | ||
60 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, | 64 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
65 | CMD_TEMPL_PS_POLL, NULL, | ||
61 | sizeof(struct wl12xx_ps_poll_template), | 66 | sizeof(struct wl12xx_ps_poll_template), |
62 | 0, WL1271_RATE_AUTOMATIC); | 67 | 0, WL1271_RATE_AUTOMATIC); |
63 | if (ret < 0) | 68 | if (ret < 0) |
64 | return ret; | 69 | return ret; |
65 | 70 | ||
66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | 71 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
72 | CMD_TEMPL_QOS_NULL_DATA, NULL, | ||
67 | sizeof | 73 | sizeof |
68 | (struct ieee80211_qos_hdr), | 74 | (struct ieee80211_qos_hdr), |
69 | 0, WL1271_RATE_AUTOMATIC); | 75 | 0, WL1271_RATE_AUTOMATIC); |
70 | if (ret < 0) | 76 | if (ret < 0) |
71 | return ret; | 77 | return ret; |
72 | 78 | ||
73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, | 79 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
80 | CMD_TEMPL_PROBE_RESPONSE, NULL, | ||
74 | WL1271_CMD_TEMPL_DFLT_SIZE, | 81 | WL1271_CMD_TEMPL_DFLT_SIZE, |
75 | 0, WL1271_RATE_AUTOMATIC); | 82 | 0, WL1271_RATE_AUTOMATIC); |
76 | if (ret < 0) | 83 | if (ret < 0) |
77 | return ret; | 84 | return ret; |
78 | 85 | ||
79 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, | 86 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
87 | CMD_TEMPL_BEACON, NULL, | ||
80 | WL1271_CMD_TEMPL_DFLT_SIZE, | 88 | WL1271_CMD_TEMPL_DFLT_SIZE, |
81 | 0, WL1271_RATE_AUTOMATIC); | 89 | 0, WL1271_RATE_AUTOMATIC); |
82 | if (ret < 0) | 90 | if (ret < 0) |
83 | return ret; | 91 | return ret; |
84 | 92 | ||
85 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL, | 93 | max_size = sizeof(struct wl12xx_arp_rsp_template) + |
86 | sizeof | 94 | WL1271_EXTRA_SPACE_MAX; |
87 | (struct wl12xx_arp_rsp_template), | 95 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
96 | CMD_TEMPL_ARP_RSP, NULL, | ||
97 | max_size, | ||
88 | 0, WL1271_RATE_AUTOMATIC); | 98 | 0, WL1271_RATE_AUTOMATIC); |
89 | if (ret < 0) | 99 | if (ret < 0) |
90 | return ret; | 100 | return ret; |
@@ -93,19 +103,22 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
93 | * Put very large empty placeholders for all templates. These | 103 | * Put very large empty placeholders for all templates. These |
94 | * reserve memory for later. | 104 | * reserve memory for later. |
95 | */ | 105 | */ |
96 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, | 106 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
107 | CMD_TEMPL_AP_PROBE_RESPONSE, NULL, | ||
97 | WL1271_CMD_TEMPL_MAX_SIZE, | 108 | WL1271_CMD_TEMPL_MAX_SIZE, |
98 | 0, WL1271_RATE_AUTOMATIC); | 109 | 0, WL1271_RATE_AUTOMATIC); |
99 | if (ret < 0) | 110 | if (ret < 0) |
100 | return ret; | 111 | return ret; |
101 | 112 | ||
102 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, | 113 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
114 | CMD_TEMPL_AP_BEACON, NULL, | ||
103 | WL1271_CMD_TEMPL_MAX_SIZE, | 115 | WL1271_CMD_TEMPL_MAX_SIZE, |
104 | 0, WL1271_RATE_AUTOMATIC); | 116 | 0, WL1271_RATE_AUTOMATIC); |
105 | if (ret < 0) | 117 | if (ret < 0) |
106 | return ret; | 118 | return ret; |
107 | 119 | ||
108 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, | 120 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
121 | CMD_TEMPL_DEAUTH_AP, NULL, | ||
109 | sizeof | 122 | sizeof |
110 | (struct wl12xx_disconn_template), | 123 | (struct wl12xx_disconn_template), |
111 | 0, WL1271_RATE_AUTOMATIC); | 124 | 0, WL1271_RATE_AUTOMATIC); |
@@ -113,7 +126,8 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
113 | return ret; | 126 | return ret; |
114 | 127 | ||
115 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | 128 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { |
116 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | 129 | ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, |
130 | CMD_TEMPL_KLV, NULL, | ||
117 | sizeof(struct ieee80211_qos_hdr), | 131 | sizeof(struct ieee80211_qos_hdr), |
118 | i, WL1271_RATE_AUTOMATIC); | 132 | i, WL1271_RATE_AUTOMATIC); |
119 | if (ret < 0) | 133 | if (ret < 0) |
@@ -140,7 +154,8 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl, | |||
140 | IEEE80211_STYPE_DEAUTH); | 154 | IEEE80211_STYPE_DEAUTH); |
141 | 155 | ||
142 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 156 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
143 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, | 157 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
158 | CMD_TEMPL_DEAUTH_AP, | ||
144 | tmpl, sizeof(*tmpl), 0, rate); | 159 | tmpl, sizeof(*tmpl), 0, rate); |
145 | 160 | ||
146 | out: | 161 | out: |
@@ -172,7 +187,8 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl, | |||
172 | memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); | 187 | memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); |
173 | 188 | ||
174 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 189 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
175 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, | 190 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
191 | CMD_TEMPL_NULL_DATA, nullfunc, | ||
176 | sizeof(*nullfunc), 0, rate); | 192 | sizeof(*nullfunc), 0, rate); |
177 | 193 | ||
178 | out: | 194 | out: |
@@ -204,7 +220,8 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, | |||
204 | memcpy(qosnull->addr3, vif->addr, ETH_ALEN); | 220 | memcpy(qosnull->addr3, vif->addr, ETH_ALEN); |
205 | 221 | ||
206 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 222 | rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
207 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, | 223 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
224 | CMD_TEMPL_QOS_NULL_DATA, qosnull, | ||
208 | sizeof(*qosnull), 0, rate); | 225 | sizeof(*qosnull), 0, rate); |
209 | 226 | ||
210 | out: | 227 | out: |
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index 079ad380e8ff..c574a3b31e31 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c | |||
@@ -45,6 +45,65 @@ | |||
45 | #define OCP_STATUS_REQ_FAILED 0x20000 | 45 | #define OCP_STATUS_REQ_FAILED 0x20000 |
46 | #define OCP_STATUS_RESP_ERROR 0x30000 | 46 | #define OCP_STATUS_RESP_ERROR 0x30000 |
47 | 47 | ||
48 | struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = { | ||
49 | [PART_DOWN] = { | ||
50 | .mem = { | ||
51 | .start = 0x00000000, | ||
52 | .size = 0x000177c0 | ||
53 | }, | ||
54 | .reg = { | ||
55 | .start = REGISTERS_BASE, | ||
56 | .size = 0x00008800 | ||
57 | }, | ||
58 | .mem2 = { | ||
59 | .start = 0x00000000, | ||
60 | .size = 0x00000000 | ||
61 | }, | ||
62 | .mem3 = { | ||
63 | .start = 0x00000000, | ||
64 | .size = 0x00000000 | ||
65 | }, | ||
66 | }, | ||
67 | |||
68 | [PART_WORK] = { | ||
69 | .mem = { | ||
70 | .start = 0x00040000, | ||
71 | .size = 0x00014fc0 | ||
72 | }, | ||
73 | .reg = { | ||
74 | .start = REGISTERS_BASE, | ||
75 | .size = 0x0000a000 | ||
76 | }, | ||
77 | .mem2 = { | ||
78 | .start = 0x003004f8, | ||
79 | .size = 0x00000004 | ||
80 | }, | ||
81 | .mem3 = { | ||
82 | .start = 0x00040404, | ||
83 | .size = 0x00000000 | ||
84 | }, | ||
85 | }, | ||
86 | |||
87 | [PART_DRPW] = { | ||
88 | .mem = { | ||
89 | .start = 0x00040000, | ||
90 | .size = 0x00014fc0 | ||
91 | }, | ||
92 | .reg = { | ||
93 | .start = DRPW_BASE, | ||
94 | .size = 0x00006000 | ||
95 | }, | ||
96 | .mem2 = { | ||
97 | .start = 0x00000000, | ||
98 | .size = 0x00000000 | ||
99 | }, | ||
100 | .mem3 = { | ||
101 | .start = 0x00000000, | ||
102 | .size = 0x00000000 | ||
103 | } | ||
104 | } | ||
105 | }; | ||
106 | |||
48 | bool wl1271_set_block_size(struct wl1271 *wl) | 107 | bool wl1271_set_block_size(struct wl1271 *wl) |
49 | { | 108 | { |
50 | if (wl->if_ops->set_block_size) { | 109 | if (wl->if_ops->set_block_size) { |
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index d398cbcea986..4fb3dab8c3b2 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h | |||
@@ -43,6 +43,8 @@ | |||
43 | 43 | ||
44 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | 44 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 |
45 | 45 | ||
46 | extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN]; | ||
47 | |||
46 | struct wl1271; | 48 | struct wl1271; |
47 | 49 | ||
48 | void wl1271_disable_interrupts(struct wl1271 *wl); | 50 | void wl1271_disable_interrupts(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f8748cedbae1..adf9bbcf88fd 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | * This file is part of wl1271 | 3 | * This file is part of wl1271 |
3 | * | 4 | * |
@@ -115,6 +116,9 @@ static struct conf_drv_settings default_conf = { | |||
115 | [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, | 116 | [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, |
116 | [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, | 117 | [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, |
117 | [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, | 118 | [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, |
119 | /* CTS Diluting params */ | ||
120 | [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, | ||
121 | [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, | ||
118 | }, | 122 | }, |
119 | .state = CONF_SG_PROTECTIVE, | 123 | .state = CONF_SG_PROTECTIVE, |
120 | }, | 124 | }, |
@@ -217,6 +221,8 @@ static struct conf_drv_settings default_conf = { | |||
217 | .conn = { | 221 | .conn = { |
218 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
219 | .listen_interval = 1, | 223 | .listen_interval = 1, |
224 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, | ||
225 | .suspend_listen_interval = 3, | ||
220 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 226 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
221 | .bcn_filt_ie_count = 2, | 227 | .bcn_filt_ie_count = 2, |
222 | .bcn_filt_ie = { | 228 | .bcn_filt_ie = { |
@@ -235,12 +241,13 @@ static struct conf_drv_settings default_conf = { | |||
235 | .broadcast_timeout = 20000, | 241 | .broadcast_timeout = 20000, |
236 | .rx_broadcast_in_ps = 1, | 242 | .rx_broadcast_in_ps = 1, |
237 | .ps_poll_threshold = 10, | 243 | .ps_poll_threshold = 10, |
238 | .ps_poll_recovery_period = 700, | ||
239 | .bet_enable = CONF_BET_MODE_ENABLE, | 244 | .bet_enable = CONF_BET_MODE_ENABLE, |
240 | .bet_max_consecutive = 50, | 245 | .bet_max_consecutive = 50, |
241 | .psm_entry_retries = 8, | 246 | .psm_entry_retries = 8, |
242 | .psm_exit_retries = 16, | 247 | .psm_exit_retries = 16, |
243 | .psm_entry_nullfunc_retries = 3, | 248 | .psm_entry_nullfunc_retries = 3, |
249 | .dynamic_ps_timeout = 100, | ||
250 | .forced_ps = false, | ||
244 | .keep_alive_interval = 55000, | 251 | .keep_alive_interval = 55000, |
245 | .max_listen_interval = 20, | 252 | .max_listen_interval = 20, |
246 | }, | 253 | }, |
@@ -265,6 +272,7 @@ static struct conf_drv_settings default_conf = { | |||
265 | .min_dwell_time_passive = 100000, | 272 | .min_dwell_time_passive = 100000, |
266 | .max_dwell_time_passive = 100000, | 273 | .max_dwell_time_passive = 100000, |
267 | .num_probe_reqs = 2, | 274 | .num_probe_reqs = 2, |
275 | .split_scan_timeout = 50000, | ||
268 | }, | 276 | }, |
269 | .sched_scan = { | 277 | .sched_scan = { |
270 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | 278 | /* sched_scan requires dwell times in TU instead of TU/1000 */ |
@@ -672,8 +680,6 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
672 | if (ret < 0) | 680 | if (ret < 0) |
673 | return ret; | 681 | return ret; |
674 | } | 682 | } |
675 | if (ret < 0) | ||
676 | return ret; | ||
677 | 683 | ||
678 | /* Chip-specific initializations */ | 684 | /* Chip-specific initializations */ |
679 | ret = wl1271_chip_specific_init(wl); | 685 | ret = wl1271_chip_specific_init(wl); |
@@ -985,16 +991,70 @@ out: | |||
985 | return IRQ_HANDLED; | 991 | return IRQ_HANDLED; |
986 | } | 992 | } |
987 | 993 | ||
988 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 994 | struct vif_counter_data { |
995 | u8 counter; | ||
996 | |||
997 | struct ieee80211_vif *cur_vif; | ||
998 | bool cur_vif_running; | ||
999 | }; | ||
1000 | |||
1001 | static void wl12xx_vif_count_iter(void *data, u8 *mac, | ||
1002 | struct ieee80211_vif *vif) | ||
1003 | { | ||
1004 | struct vif_counter_data *counter = data; | ||
1005 | |||
1006 | counter->counter++; | ||
1007 | if (counter->cur_vif == vif) | ||
1008 | counter->cur_vif_running = true; | ||
1009 | } | ||
1010 | |||
1011 | /* caller must not hold wl->mutex, as it might deadlock */ | ||
1012 | static void wl12xx_get_vif_count(struct ieee80211_hw *hw, | ||
1013 | struct ieee80211_vif *cur_vif, | ||
1014 | struct vif_counter_data *data) | ||
1015 | { | ||
1016 | memset(data, 0, sizeof(*data)); | ||
1017 | data->cur_vif = cur_vif; | ||
1018 | |||
1019 | ieee80211_iterate_active_interfaces(hw, | ||
1020 | wl12xx_vif_count_iter, data); | ||
1021 | } | ||
1022 | |||
1023 | static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) | ||
989 | { | 1024 | { |
990 | const struct firmware *fw; | 1025 | const struct firmware *fw; |
991 | const char *fw_name; | 1026 | const char *fw_name; |
1027 | enum wl12xx_fw_type fw_type; | ||
992 | int ret; | 1028 | int ret; |
993 | 1029 | ||
994 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1030 | if (plt) { |
995 | fw_name = WL128X_FW_NAME; | 1031 | fw_type = WL12XX_FW_TYPE_PLT; |
996 | else | 1032 | if (wl->chip.id == CHIP_ID_1283_PG20) |
997 | fw_name = WL127X_FW_NAME; | 1033 | fw_name = WL128X_PLT_FW_NAME; |
1034 | else | ||
1035 | fw_name = WL127X_PLT_FW_NAME; | ||
1036 | } else { | ||
1037 | /* | ||
1038 | * we can't call wl12xx_get_vif_count() here because | ||
1039 | * wl->mutex is taken, so use the cached last_vif_count value | ||
1040 | */ | ||
1041 | if (wl->last_vif_count > 1) { | ||
1042 | fw_type = WL12XX_FW_TYPE_MULTI; | ||
1043 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1044 | fw_name = WL128X_FW_NAME_MULTI; | ||
1045 | else | ||
1046 | fw_name = WL127X_FW_NAME_MULTI; | ||
1047 | } else { | ||
1048 | fw_type = WL12XX_FW_TYPE_NORMAL; | ||
1049 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1050 | fw_name = WL128X_FW_NAME_SINGLE; | ||
1051 | else | ||
1052 | fw_name = WL127X_FW_NAME_SINGLE; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | if (wl->fw_type == fw_type) | ||
1057 | return 0; | ||
998 | 1058 | ||
999 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); | 1059 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); |
1000 | 1060 | ||
@@ -1013,6 +1073,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
1013 | } | 1073 | } |
1014 | 1074 | ||
1015 | vfree(wl->fw); | 1075 | vfree(wl->fw); |
1076 | wl->fw_type = WL12XX_FW_TYPE_NONE; | ||
1016 | wl->fw_len = fw->size; | 1077 | wl->fw_len = fw->size; |
1017 | wl->fw = vmalloc(wl->fw_len); | 1078 | wl->fw = vmalloc(wl->fw_len); |
1018 | 1079 | ||
@@ -1024,7 +1085,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
1024 | 1085 | ||
1025 | memcpy(wl->fw, fw->data, wl->fw_len); | 1086 | memcpy(wl->fw, fw->data, wl->fw_len); |
1026 | ret = 0; | 1087 | ret = 0; |
1027 | 1088 | wl->fw_type = fw_type; | |
1028 | out: | 1089 | out: |
1029 | release_firmware(fw); | 1090 | release_firmware(fw); |
1030 | 1091 | ||
@@ -1152,7 +1213,7 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1152 | 1213 | ||
1153 | mutex_lock(&wl->mutex); | 1214 | mutex_lock(&wl->mutex); |
1154 | 1215 | ||
1155 | if (wl->state != WL1271_STATE_ON) | 1216 | if (wl->state != WL1271_STATE_ON || wl->plt) |
1156 | goto out_unlock; | 1217 | goto out_unlock; |
1157 | 1218 | ||
1158 | /* Avoid a recursive recovery */ | 1219 | /* Avoid a recursive recovery */ |
@@ -1232,10 +1293,9 @@ static int wl1271_setup(struct wl1271 *wl) | |||
1232 | return 0; | 1293 | return 0; |
1233 | } | 1294 | } |
1234 | 1295 | ||
1235 | static int wl1271_chip_wakeup(struct wl1271 *wl) | 1296 | static int wl12xx_set_power_on(struct wl1271 *wl) |
1236 | { | 1297 | { |
1237 | struct wl1271_partition_set partition; | 1298 | int ret; |
1238 | int ret = 0; | ||
1239 | 1299 | ||
1240 | msleep(WL1271_PRE_POWER_ON_SLEEP); | 1300 | msleep(WL1271_PRE_POWER_ON_SLEEP); |
1241 | ret = wl1271_power_on(wl); | 1301 | ret = wl1271_power_on(wl); |
@@ -1245,20 +1305,22 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1245 | wl1271_io_reset(wl); | 1305 | wl1271_io_reset(wl); |
1246 | wl1271_io_init(wl); | 1306 | wl1271_io_init(wl); |
1247 | 1307 | ||
1248 | /* We don't need a real memory partition here, because we only want | 1308 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); |
1249 | * to use the registers at this point. */ | ||
1250 | memset(&partition, 0, sizeof(partition)); | ||
1251 | partition.reg.start = REGISTERS_BASE; | ||
1252 | partition.reg.size = REGISTERS_DOWN_SIZE; | ||
1253 | wl1271_set_partition(wl, &partition); | ||
1254 | 1309 | ||
1255 | /* ELP module wake up */ | 1310 | /* ELP module wake up */ |
1256 | wl1271_fw_wakeup(wl); | 1311 | wl1271_fw_wakeup(wl); |
1257 | 1312 | ||
1258 | /* whal_FwCtrl_BootSm() */ | 1313 | out: |
1314 | return ret; | ||
1315 | } | ||
1259 | 1316 | ||
1260 | /* 0. read chip id from CHIP_ID */ | 1317 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) |
1261 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); | 1318 | { |
1319 | int ret = 0; | ||
1320 | |||
1321 | ret = wl12xx_set_power_on(wl); | ||
1322 | if (ret < 0) | ||
1323 | goto out; | ||
1262 | 1324 | ||
1263 | /* | 1325 | /* |
1264 | * For wl127x based devices we could use the default block | 1326 | * For wl127x based devices we could use the default block |
@@ -1307,11 +1369,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1307 | goto out; | 1369 | goto out; |
1308 | } | 1370 | } |
1309 | 1371 | ||
1310 | if (wl->fw == NULL) { | 1372 | ret = wl12xx_fetch_firmware(wl, plt); |
1311 | ret = wl1271_fetch_firmware(wl); | 1373 | if (ret < 0) |
1312 | if (ret < 0) | 1374 | goto out; |
1313 | goto out; | ||
1314 | } | ||
1315 | 1375 | ||
1316 | /* No NVS from netlink, try to get it from the filesystem */ | 1376 | /* No NVS from netlink, try to get it from the filesystem */ |
1317 | if (wl->nvs == NULL) { | 1377 | if (wl->nvs == NULL) { |
@@ -1343,7 +1403,7 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1343 | 1403 | ||
1344 | while (retries) { | 1404 | while (retries) { |
1345 | retries--; | 1405 | retries--; |
1346 | ret = wl1271_chip_wakeup(wl); | 1406 | ret = wl12xx_chip_wakeup(wl, true); |
1347 | if (ret < 0) | 1407 | if (ret < 0) |
1348 | goto power_off; | 1408 | goto power_off; |
1349 | 1409 | ||
@@ -1355,7 +1415,8 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1355 | if (ret < 0) | 1415 | if (ret < 0) |
1356 | goto irq_disable; | 1416 | goto irq_disable; |
1357 | 1417 | ||
1358 | wl->state = WL1271_STATE_PLT; | 1418 | wl->plt = true; |
1419 | wl->state = WL1271_STATE_ON; | ||
1359 | wl1271_notice("firmware booted in PLT mode (%s)", | 1420 | wl1271_notice("firmware booted in PLT mode (%s)", |
1360 | wl->chip.fw_ver_str); | 1421 | wl->chip.fw_ver_str); |
1361 | 1422 | ||
@@ -1391,41 +1452,51 @@ out: | |||
1391 | return ret; | 1452 | return ret; |
1392 | } | 1453 | } |
1393 | 1454 | ||
1394 | static int __wl1271_plt_stop(struct wl1271 *wl) | 1455 | int wl1271_plt_stop(struct wl1271 *wl) |
1395 | { | 1456 | { |
1396 | int ret = 0; | 1457 | int ret = 0; |
1397 | 1458 | ||
1398 | wl1271_notice("power down"); | 1459 | wl1271_notice("power down"); |
1399 | 1460 | ||
1400 | if (wl->state != WL1271_STATE_PLT) { | 1461 | /* |
1462 | * Interrupts must be disabled before setting the state to OFF. | ||
1463 | * Otherwise, the interrupt handler might be called and exit without | ||
1464 | * reading the interrupt status. | ||
1465 | */ | ||
1466 | wl1271_disable_interrupts(wl); | ||
1467 | mutex_lock(&wl->mutex); | ||
1468 | if (!wl->plt) { | ||
1469 | mutex_unlock(&wl->mutex); | ||
1470 | |||
1471 | /* | ||
1472 | * This will not necessarily enable interrupts as interrupts | ||
1473 | * may have been disabled when op_stop was called. It will, | ||
1474 | * however, balance the above call to disable_interrupts(). | ||
1475 | */ | ||
1476 | wl1271_enable_interrupts(wl); | ||
1477 | |||
1401 | wl1271_error("cannot power down because not in PLT " | 1478 | wl1271_error("cannot power down because not in PLT " |
1402 | "state: %d", wl->state); | 1479 | "state: %d", wl->state); |
1403 | ret = -EBUSY; | 1480 | ret = -EBUSY; |
1404 | goto out; | 1481 | goto out; |
1405 | } | 1482 | } |
1406 | 1483 | ||
1407 | wl1271_power_off(wl); | ||
1408 | |||
1409 | wl->state = WL1271_STATE_OFF; | ||
1410 | wl->rx_counter = 0; | ||
1411 | |||
1412 | mutex_unlock(&wl->mutex); | 1484 | mutex_unlock(&wl->mutex); |
1413 | wl1271_disable_interrupts(wl); | 1485 | |
1414 | wl1271_flush_deferred_work(wl); | 1486 | wl1271_flush_deferred_work(wl); |
1415 | cancel_work_sync(&wl->netstack_work); | 1487 | cancel_work_sync(&wl->netstack_work); |
1416 | cancel_work_sync(&wl->recovery_work); | 1488 | cancel_work_sync(&wl->recovery_work); |
1417 | mutex_lock(&wl->mutex); | 1489 | cancel_delayed_work_sync(&wl->elp_work); |
1418 | out: | ||
1419 | return ret; | ||
1420 | } | ||
1421 | |||
1422 | int wl1271_plt_stop(struct wl1271 *wl) | ||
1423 | { | ||
1424 | int ret; | ||
1425 | 1490 | ||
1426 | mutex_lock(&wl->mutex); | 1491 | mutex_lock(&wl->mutex); |
1427 | ret = __wl1271_plt_stop(wl); | 1492 | wl1271_power_off(wl); |
1493 | wl->flags = 0; | ||
1494 | wl->state = WL1271_STATE_OFF; | ||
1495 | wl->plt = false; | ||
1496 | wl->rx_counter = 0; | ||
1428 | mutex_unlock(&wl->mutex); | 1497 | mutex_unlock(&wl->mutex); |
1498 | |||
1499 | out: | ||
1429 | return ret; | 1500 | return ret; |
1430 | } | 1501 | } |
1431 | 1502 | ||
@@ -1574,38 +1645,16 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1574 | if (ret < 0) | 1645 | if (ret < 0) |
1575 | goto out_unlock; | 1646 | goto out_unlock; |
1576 | 1647 | ||
1577 | /* enter psm if needed*/ | 1648 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1578 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | 1649 | wl->conf.conn.suspend_wake_up_event, |
1579 | DECLARE_COMPLETION_ONSTACK(compl); | 1650 | wl->conf.conn.suspend_listen_interval); |
1580 | 1651 | ||
1581 | wlvif->ps_compl = &compl; | 1652 | if (ret < 0) |
1582 | ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, | 1653 | wl1271_error("suspend: set wake up conditions failed: %d", ret); |
1583 | wlvif->basic_rate, true); | ||
1584 | if (ret < 0) | ||
1585 | goto out_sleep; | ||
1586 | |||
1587 | /* we must unlock here so we will be able to get events */ | ||
1588 | wl1271_ps_elp_sleep(wl); | ||
1589 | mutex_unlock(&wl->mutex); | ||
1590 | |||
1591 | ret = wait_for_completion_timeout( | ||
1592 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | ||
1593 | 1654 | ||
1594 | mutex_lock(&wl->mutex); | ||
1595 | if (ret <= 0) { | ||
1596 | wl1271_warning("couldn't enter ps mode!"); | ||
1597 | ret = -EBUSY; | ||
1598 | goto out_cleanup; | ||
1599 | } | ||
1600 | 1655 | ||
1601 | ret = wl1271_ps_elp_wakeup(wl); | ||
1602 | if (ret < 0) | ||
1603 | goto out_cleanup; | ||
1604 | } | ||
1605 | out_sleep: | ||
1606 | wl1271_ps_elp_sleep(wl); | 1656 | wl1271_ps_elp_sleep(wl); |
1607 | out_cleanup: | 1657 | |
1608 | wlvif->ps_compl = NULL; | ||
1609 | out_unlock: | 1658 | out_unlock: |
1610 | mutex_unlock(&wl->mutex); | 1659 | mutex_unlock(&wl->mutex); |
1611 | return ret; | 1660 | return ret; |
@@ -1648,11 +1697,11 @@ static int wl1271_configure_suspend(struct wl1271 *wl, | |||
1648 | static void wl1271_configure_resume(struct wl1271 *wl, | 1697 | static void wl1271_configure_resume(struct wl1271 *wl, |
1649 | struct wl12xx_vif *wlvif) | 1698 | struct wl12xx_vif *wlvif) |
1650 | { | 1699 | { |
1651 | int ret; | 1700 | int ret = 0; |
1652 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; | ||
1653 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; | 1701 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; |
1702 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; | ||
1654 | 1703 | ||
1655 | if (!is_sta && !is_ap) | 1704 | if ((!is_ap) && (!is_sta)) |
1656 | return; | 1705 | return; |
1657 | 1706 | ||
1658 | mutex_lock(&wl->mutex); | 1707 | mutex_lock(&wl->mutex); |
@@ -1661,12 +1710,16 @@ static void wl1271_configure_resume(struct wl1271 *wl, | |||
1661 | goto out; | 1710 | goto out; |
1662 | 1711 | ||
1663 | if (is_sta) { | 1712 | if (is_sta) { |
1664 | /* exit psm if it wasn't configured */ | 1713 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1665 | if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) | 1714 | wl->conf.conn.wake_up_event, |
1666 | wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, | 1715 | wl->conf.conn.listen_interval); |
1667 | wlvif->basic_rate, true); | 1716 | |
1717 | if (ret < 0) | ||
1718 | wl1271_error("resume: wake up conditions failed: %d", | ||
1719 | ret); | ||
1720 | |||
1668 | } else if (is_ap) { | 1721 | } else if (is_ap) { |
1669 | wl1271_acx_beacon_filter_opt(wl, wlvif, false); | 1722 | ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); |
1670 | } | 1723 | } |
1671 | 1724 | ||
1672 | wl1271_ps_elp_sleep(wl); | 1725 | wl1271_ps_elp_sleep(wl); |
@@ -1709,9 +1762,6 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1709 | 1762 | ||
1710 | wl1271_enable_interrupts(wl); | 1763 | wl1271_enable_interrupts(wl); |
1711 | flush_work(&wl->tx_work); | 1764 | flush_work(&wl->tx_work); |
1712 | wl12xx_for_each_wlvif(wl, wlvif) { | ||
1713 | flush_delayed_work(&wlvif->pspoll_work); | ||
1714 | } | ||
1715 | flush_delayed_work(&wl->elp_work); | 1765 | flush_delayed_work(&wl->elp_work); |
1716 | 1766 | ||
1717 | return 0; | 1767 | return 0; |
@@ -1778,11 +1828,25 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1778 | 1828 | ||
1779 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | 1829 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); |
1780 | 1830 | ||
1831 | /* | ||
1832 | * Interrupts must be disabled before setting the state to OFF. | ||
1833 | * Otherwise, the interrupt handler might be called and exit without | ||
1834 | * reading the interrupt status. | ||
1835 | */ | ||
1836 | wl1271_disable_interrupts(wl); | ||
1781 | mutex_lock(&wl->mutex); | 1837 | mutex_lock(&wl->mutex); |
1782 | if (wl->state == WL1271_STATE_OFF) { | 1838 | if (wl->state == WL1271_STATE_OFF) { |
1783 | mutex_unlock(&wl->mutex); | 1839 | mutex_unlock(&wl->mutex); |
1840 | |||
1841 | /* | ||
1842 | * This will not necessarily enable interrupts as interrupts | ||
1843 | * may have been disabled when op_stop was called. It will, | ||
1844 | * however, balance the above call to disable_interrupts(). | ||
1845 | */ | ||
1846 | wl1271_enable_interrupts(wl); | ||
1784 | return; | 1847 | return; |
1785 | } | 1848 | } |
1849 | |||
1786 | /* | 1850 | /* |
1787 | * this must be before the cancel_work calls below, so that the work | 1851 | * this must be before the cancel_work calls below, so that the work |
1788 | * functions don't perform further work. | 1852 | * functions don't perform further work. |
@@ -1794,7 +1858,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1794 | list_del(&wl->list); | 1858 | list_del(&wl->list); |
1795 | mutex_unlock(&wl_list_mutex); | 1859 | mutex_unlock(&wl_list_mutex); |
1796 | 1860 | ||
1797 | wl1271_disable_interrupts(wl); | ||
1798 | wl1271_flush_deferred_work(wl); | 1861 | wl1271_flush_deferred_work(wl); |
1799 | cancel_delayed_work_sync(&wl->scan_complete_work); | 1862 | cancel_delayed_work_sync(&wl->scan_complete_work); |
1800 | cancel_work_sync(&wl->netstack_work); | 1863 | cancel_work_sync(&wl->netstack_work); |
@@ -1969,7 +2032,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1969 | wl1271_rx_streaming_enable_work); | 2032 | wl1271_rx_streaming_enable_work); |
1970 | INIT_WORK(&wlvif->rx_streaming_disable_work, | 2033 | INIT_WORK(&wlvif->rx_streaming_disable_work, |
1971 | wl1271_rx_streaming_disable_work); | 2034 | wl1271_rx_streaming_disable_work); |
1972 | INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); | ||
1973 | INIT_LIST_HEAD(&wlvif->list); | 2035 | INIT_LIST_HEAD(&wlvif->list); |
1974 | 2036 | ||
1975 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, | 2037 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, |
@@ -1986,7 +2048,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) | |||
1986 | 2048 | ||
1987 | while (retries) { | 2049 | while (retries) { |
1988 | retries--; | 2050 | retries--; |
1989 | ret = wl1271_chip_wakeup(wl); | 2051 | ret = wl12xx_chip_wakeup(wl, false); |
1990 | if (ret < 0) | 2052 | if (ret < 0) |
1991 | goto power_off; | 2053 | goto power_off; |
1992 | 2054 | ||
@@ -2051,11 +2113,60 @@ static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif) | |||
2051 | return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID; | 2113 | return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID; |
2052 | } | 2114 | } |
2053 | 2115 | ||
2116 | /* | ||
2117 | * Check whether a fw switch (i.e. moving from one loaded | ||
2118 | * fw to another) is needed. This function is also responsible | ||
2119 | * for updating wl->last_vif_count, so it must be called before | ||
2120 | * loading a non-plt fw (so the correct fw (single-role/multi-role) | ||
2121 | * will be used). | ||
2122 | */ | ||
2123 | static bool wl12xx_need_fw_change(struct wl1271 *wl, | ||
2124 | struct vif_counter_data vif_counter_data, | ||
2125 | bool add) | ||
2126 | { | ||
2127 | enum wl12xx_fw_type current_fw = wl->fw_type; | ||
2128 | u8 vif_count = vif_counter_data.counter; | ||
2129 | |||
2130 | if (test_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags)) | ||
2131 | return false; | ||
2132 | |||
2133 | /* increase the vif count if this is a new vif */ | ||
2134 | if (add && !vif_counter_data.cur_vif_running) | ||
2135 | vif_count++; | ||
2136 | |||
2137 | wl->last_vif_count = vif_count; | ||
2138 | |||
2139 | /* no need for fw change if the device is OFF */ | ||
2140 | if (wl->state == WL1271_STATE_OFF) | ||
2141 | return false; | ||
2142 | |||
2143 | if (vif_count > 1 && current_fw == WL12XX_FW_TYPE_NORMAL) | ||
2144 | return true; | ||
2145 | if (vif_count <= 1 && current_fw == WL12XX_FW_TYPE_MULTI) | ||
2146 | return true; | ||
2147 | |||
2148 | return false; | ||
2149 | } | ||
2150 | |||
2151 | /* | ||
2152 | * Enter "forced psm". Make sure the sta is in psm against the ap, | ||
2153 | * to make the fw switch a bit more disconnection-persistent. | ||
2154 | */ | ||
2155 | static void wl12xx_force_active_psm(struct wl1271 *wl) | ||
2156 | { | ||
2157 | struct wl12xx_vif *wlvif; | ||
2158 | |||
2159 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
2160 | wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE); | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2054 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 2164 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
2055 | struct ieee80211_vif *vif) | 2165 | struct ieee80211_vif *vif) |
2056 | { | 2166 | { |
2057 | struct wl1271 *wl = hw->priv; | 2167 | struct wl1271 *wl = hw->priv; |
2058 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 2168 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2169 | struct vif_counter_data vif_count; | ||
2059 | int ret = 0; | 2170 | int ret = 0; |
2060 | u8 role_type; | 2171 | u8 role_type; |
2061 | bool booted = false; | 2172 | bool booted = false; |
@@ -2066,18 +2177,13 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2066 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 2177 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
2067 | ieee80211_vif_type_p2p(vif), vif->addr); | 2178 | ieee80211_vif_type_p2p(vif), vif->addr); |
2068 | 2179 | ||
2180 | wl12xx_get_vif_count(hw, vif, &vif_count); | ||
2181 | |||
2069 | mutex_lock(&wl->mutex); | 2182 | mutex_lock(&wl->mutex); |
2070 | ret = wl1271_ps_elp_wakeup(wl); | 2183 | ret = wl1271_ps_elp_wakeup(wl); |
2071 | if (ret < 0) | 2184 | if (ret < 0) |
2072 | goto out_unlock; | 2185 | goto out_unlock; |
2073 | 2186 | ||
2074 | if (wl->vif) { | ||
2075 | wl1271_debug(DEBUG_MAC80211, | ||
2076 | "multiple vifs are not supported yet"); | ||
2077 | ret = -EBUSY; | ||
2078 | goto out; | ||
2079 | } | ||
2080 | |||
2081 | /* | 2187 | /* |
2082 | * in some very corner case HW recovery scenarios its possible to | 2188 | * in some very corner case HW recovery scenarios its possible to |
2083 | * get here before __wl1271_op_remove_interface is complete, so | 2189 | * get here before __wl1271_op_remove_interface is complete, so |
@@ -2089,6 +2195,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2089 | goto out; | 2195 | goto out; |
2090 | } | 2196 | } |
2091 | 2197 | ||
2198 | |||
2092 | ret = wl12xx_init_vif_data(wl, vif); | 2199 | ret = wl12xx_init_vif_data(wl, vif); |
2093 | if (ret < 0) | 2200 | if (ret < 0) |
2094 | goto out; | 2201 | goto out; |
@@ -2100,6 +2207,13 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2100 | goto out; | 2207 | goto out; |
2101 | } | 2208 | } |
2102 | 2209 | ||
2210 | if (wl12xx_need_fw_change(wl, vif_count, true)) { | ||
2211 | wl12xx_force_active_psm(wl); | ||
2212 | mutex_unlock(&wl->mutex); | ||
2213 | wl1271_recovery_work(&wl->recovery_work); | ||
2214 | return 0; | ||
2215 | } | ||
2216 | |||
2103 | /* | 2217 | /* |
2104 | * TODO: after the nvs issue will be solved, move this block | 2218 | * TODO: after the nvs issue will be solved, move this block |
2105 | * to start(), and make sure here the driver is ON. | 2219 | * to start(), and make sure here the driver is ON. |
@@ -2109,7 +2223,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2109 | * we still need this in order to configure the fw | 2223 | * we still need this in order to configure the fw |
2110 | * while uploading the nvs | 2224 | * while uploading the nvs |
2111 | */ | 2225 | */ |
2112 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | 2226 | memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN); |
2113 | 2227 | ||
2114 | booted = wl12xx_init_fw(wl); | 2228 | booted = wl12xx_init_fw(wl); |
2115 | if (!booted) { | 2229 | if (!booted) { |
@@ -2142,7 +2256,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
2142 | if (ret < 0) | 2256 | if (ret < 0) |
2143 | goto out; | 2257 | goto out; |
2144 | 2258 | ||
2145 | wl->vif = vif; | ||
2146 | list_add(&wlvif->list, &wl->wlvif_list); | 2259 | list_add(&wlvif->list, &wl->wlvif_list); |
2147 | set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); | 2260 | set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); |
2148 | 2261 | ||
@@ -2175,18 +2288,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2175 | if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) | 2288 | if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) |
2176 | return; | 2289 | return; |
2177 | 2290 | ||
2178 | wl->vif = NULL; | ||
2179 | |||
2180 | /* because of hardware recovery, we may get here twice */ | 2291 | /* because of hardware recovery, we may get here twice */ |
2181 | if (wl->state != WL1271_STATE_ON) | 2292 | if (wl->state != WL1271_STATE_ON) |
2182 | return; | 2293 | return; |
2183 | 2294 | ||
2184 | wl1271_info("down"); | 2295 | wl1271_info("down"); |
2185 | 2296 | ||
2186 | /* enable dyn ps just in case (if left on due to fw crash etc) */ | ||
2187 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) | ||
2188 | ieee80211_enable_dyn_ps(vif); | ||
2189 | |||
2190 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE && | 2297 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE && |
2191 | wl->scan_vif == vif) { | 2298 | wl->scan_vif == vif) { |
2192 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 2299 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
@@ -2253,10 +2360,10 @@ deinit: | |||
2253 | wl->sta_count--; | 2360 | wl->sta_count--; |
2254 | 2361 | ||
2255 | mutex_unlock(&wl->mutex); | 2362 | mutex_unlock(&wl->mutex); |
2363 | |||
2256 | del_timer_sync(&wlvif->rx_streaming_timer); | 2364 | del_timer_sync(&wlvif->rx_streaming_timer); |
2257 | cancel_work_sync(&wlvif->rx_streaming_enable_work); | 2365 | cancel_work_sync(&wlvif->rx_streaming_enable_work); |
2258 | cancel_work_sync(&wlvif->rx_streaming_disable_work); | 2366 | cancel_work_sync(&wlvif->rx_streaming_disable_work); |
2259 | cancel_delayed_work_sync(&wlvif->pspoll_work); | ||
2260 | 2367 | ||
2261 | mutex_lock(&wl->mutex); | 2368 | mutex_lock(&wl->mutex); |
2262 | } | 2369 | } |
@@ -2267,7 +2374,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
2267 | struct wl1271 *wl = hw->priv; | 2374 | struct wl1271 *wl = hw->priv; |
2268 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 2375 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2269 | struct wl12xx_vif *iter; | 2376 | struct wl12xx_vif *iter; |
2377 | struct vif_counter_data vif_count; | ||
2378 | bool cancel_recovery = true; | ||
2270 | 2379 | ||
2380 | wl12xx_get_vif_count(hw, vif, &vif_count); | ||
2271 | mutex_lock(&wl->mutex); | 2381 | mutex_lock(&wl->mutex); |
2272 | 2382 | ||
2273 | if (wl->state == WL1271_STATE_OFF || | 2383 | if (wl->state == WL1271_STATE_OFF || |
@@ -2286,20 +2396,33 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
2286 | break; | 2396 | break; |
2287 | } | 2397 | } |
2288 | WARN_ON(iter != wlvif); | 2398 | WARN_ON(iter != wlvif); |
2399 | if (wl12xx_need_fw_change(wl, vif_count, false)) { | ||
2400 | wl12xx_force_active_psm(wl); | ||
2401 | wl12xx_queue_recovery_work(wl); | ||
2402 | cancel_recovery = false; | ||
2403 | } | ||
2289 | out: | 2404 | out: |
2290 | mutex_unlock(&wl->mutex); | 2405 | mutex_unlock(&wl->mutex); |
2291 | cancel_work_sync(&wl->recovery_work); | 2406 | if (cancel_recovery) |
2407 | cancel_work_sync(&wl->recovery_work); | ||
2292 | } | 2408 | } |
2293 | 2409 | ||
2294 | static int wl12xx_op_change_interface(struct ieee80211_hw *hw, | 2410 | static int wl12xx_op_change_interface(struct ieee80211_hw *hw, |
2295 | struct ieee80211_vif *vif, | 2411 | struct ieee80211_vif *vif, |
2296 | enum nl80211_iftype new_type, bool p2p) | 2412 | enum nl80211_iftype new_type, bool p2p) |
2297 | { | 2413 | { |
2414 | struct wl1271 *wl = hw->priv; | ||
2415 | int ret; | ||
2416 | |||
2417 | set_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags); | ||
2298 | wl1271_op_remove_interface(hw, vif); | 2418 | wl1271_op_remove_interface(hw, vif); |
2299 | 2419 | ||
2300 | vif->type = ieee80211_iftype_p2p(new_type, p2p); | 2420 | vif->type = ieee80211_iftype_p2p(new_type, p2p); |
2301 | vif->p2p = p2p; | 2421 | vif->p2p = p2p; |
2302 | return wl1271_op_add_interface(hw, vif); | 2422 | ret = wl1271_op_add_interface(hw, vif); |
2423 | |||
2424 | clear_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags); | ||
2425 | return ret; | ||
2303 | } | 2426 | } |
2304 | 2427 | ||
2305 | static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 2428 | static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -2320,6 +2443,9 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2320 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | 2443 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
2321 | wl1271_info("JOIN while associated."); | 2444 | wl1271_info("JOIN while associated."); |
2322 | 2445 | ||
2446 | /* clear encryption type */ | ||
2447 | wlvif->encryption_type = KEY_NONE; | ||
2448 | |||
2323 | if (set_assoc) | 2449 | if (set_assoc) |
2324 | set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); | 2450 | set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); |
2325 | 2451 | ||
@@ -2503,38 +2629,41 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2503 | } | 2629 | } |
2504 | } | 2630 | } |
2505 | 2631 | ||
2506 | /* | 2632 | if ((changed & IEEE80211_CONF_CHANGE_PS) && !is_ap) { |
2507 | * if mac80211 changes the PSM mode, make sure the mode is not | ||
2508 | * incorrectly changed after the pspoll failure active window. | ||
2509 | */ | ||
2510 | if (changed & IEEE80211_CONF_CHANGE_PS) | ||
2511 | clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); | ||
2512 | 2633 | ||
2513 | if (conf->flags & IEEE80211_CONF_PS && | 2634 | if ((conf->flags & IEEE80211_CONF_PS) && |
2514 | !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { | 2635 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && |
2515 | set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); | 2636 | !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { |
2516 | 2637 | ||
2517 | /* | 2638 | int ps_mode; |
2518 | * We enter PSM only if we're already associated. | 2639 | char *ps_mode_str; |
2519 | * If we're not, we'll enter it when joining an SSID, | ||
2520 | * through the bss_info_changed() hook. | ||
2521 | */ | ||
2522 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { | ||
2523 | wl1271_debug(DEBUG_PSM, "psm enabled"); | ||
2524 | ret = wl1271_ps_set_mode(wl, wlvif, | ||
2525 | STATION_POWER_SAVE_MODE, | ||
2526 | wlvif->basic_rate, true); | ||
2527 | } | ||
2528 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | ||
2529 | test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { | ||
2530 | wl1271_debug(DEBUG_PSM, "psm disabled"); | ||
2531 | 2640 | ||
2532 | clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); | 2641 | if (wl->conf.conn.forced_ps) { |
2642 | ps_mode = STATION_POWER_SAVE_MODE; | ||
2643 | ps_mode_str = "forced"; | ||
2644 | } else { | ||
2645 | ps_mode = STATION_AUTO_PS_MODE; | ||
2646 | ps_mode_str = "auto"; | ||
2647 | } | ||
2648 | |||
2649 | wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str); | ||
2650 | |||
2651 | ret = wl1271_ps_set_mode(wl, wlvif, ps_mode); | ||
2652 | |||
2653 | if (ret < 0) | ||
2654 | wl1271_warning("enter %s ps failed %d", | ||
2655 | ps_mode_str, ret); | ||
2656 | |||
2657 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | ||
2658 | test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { | ||
2659 | |||
2660 | wl1271_debug(DEBUG_PSM, "auto ps disabled"); | ||
2533 | 2661 | ||
2534 | if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) | ||
2535 | ret = wl1271_ps_set_mode(wl, wlvif, | 2662 | ret = wl1271_ps_set_mode(wl, wlvif, |
2536 | STATION_ACTIVE_MODE, | 2663 | STATION_ACTIVE_MODE); |
2537 | wlvif->basic_rate, true); | 2664 | if (ret < 0) |
2665 | wl1271_warning("exit auto ps failed %d", ret); | ||
2666 | } | ||
2538 | } | 2667 | } |
2539 | 2668 | ||
2540 | if (conf->power_level != wlvif->power_level) { | 2669 | if (conf->power_level != wlvif->power_level) { |
@@ -2974,6 +3103,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2974 | wl1271_error("Could not add or replace key"); | 3103 | wl1271_error("Could not add or replace key"); |
2975 | goto out_sleep; | 3104 | goto out_sleep; |
2976 | } | 3105 | } |
3106 | |||
3107 | /* | ||
3108 | * reconfiguring arp response if the unicast (or common) | ||
3109 | * encryption key type was changed | ||
3110 | */ | ||
3111 | if (wlvif->bss_type == BSS_TYPE_STA_BSS && | ||
3112 | (sta || key_type == KEY_WEP) && | ||
3113 | wlvif->encryption_type != key_type) { | ||
3114 | wlvif->encryption_type = key_type; | ||
3115 | ret = wl1271_cmd_build_arp_rsp(wl, wlvif); | ||
3116 | if (ret < 0) { | ||
3117 | wl1271_warning("build arp rsp failed: %d", ret); | ||
3118 | goto out_sleep; | ||
3119 | } | ||
3120 | } | ||
2977 | break; | 3121 | break; |
2978 | 3122 | ||
2979 | case DISABLE_KEY: | 3123 | case DISABLE_KEY: |
@@ -3043,10 +3187,6 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
3043 | goto out_sleep; | 3187 | goto out_sleep; |
3044 | } | 3188 | } |
3045 | 3189 | ||
3046 | /* cancel ROC before scanning */ | ||
3047 | if (wl12xx_dev_role_started(wlvif)) | ||
3048 | wl12xx_stop_dev(wl, wlvif); | ||
3049 | |||
3050 | ret = wl1271_scan(hw->priv, vif, ssid, len, req); | 3190 | ret = wl1271_scan(hw->priv, vif, ssid, len, req); |
3051 | out_sleep: | 3191 | out_sleep: |
3052 | wl1271_ps_elp_sleep(wl); | 3192 | wl1271_ps_elp_sleep(wl); |
@@ -3108,6 +3248,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | |||
3108 | 3248 | ||
3109 | mutex_lock(&wl->mutex); | 3249 | mutex_lock(&wl->mutex); |
3110 | 3250 | ||
3251 | if (wl->state == WL1271_STATE_OFF) { | ||
3252 | ret = -EAGAIN; | ||
3253 | goto out; | ||
3254 | } | ||
3255 | |||
3111 | ret = wl1271_ps_elp_wakeup(wl); | 3256 | ret = wl1271_ps_elp_wakeup(wl); |
3112 | if (ret < 0) | 3257 | if (ret < 0) |
3113 | goto out; | 3258 | goto out; |
@@ -3139,6 +3284,9 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | |||
3139 | 3284 | ||
3140 | mutex_lock(&wl->mutex); | 3285 | mutex_lock(&wl->mutex); |
3141 | 3286 | ||
3287 | if (wl->state == WL1271_STATE_OFF) | ||
3288 | goto out; | ||
3289 | |||
3142 | ret = wl1271_ps_elp_wakeup(wl); | 3290 | ret = wl1271_ps_elp_wakeup(wl); |
3143 | if (ret < 0) | 3291 | if (ret < 0) |
3144 | goto out; | 3292 | goto out; |
@@ -3266,6 +3414,7 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, | |||
3266 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, | 3414 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, |
3267 | struct ieee80211_vif *vif) | 3415 | struct ieee80211_vif *vif) |
3268 | { | 3416 | { |
3417 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3269 | struct sk_buff *skb; | 3418 | struct sk_buff *skb; |
3270 | int ret; | 3419 | int ret; |
3271 | 3420 | ||
@@ -3273,7 +3422,7 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, | |||
3273 | if (!skb) | 3422 | if (!skb) |
3274 | return -EOPNOTSUPP; | 3423 | return -EOPNOTSUPP; |
3275 | 3424 | ||
3276 | ret = wl1271_cmd_template_set(wl, | 3425 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
3277 | CMD_TEMPL_AP_PROBE_RESPONSE, | 3426 | CMD_TEMPL_AP_PROBE_RESPONSE, |
3278 | skb->data, | 3427 | skb->data, |
3279 | skb->len, 0, | 3428 | skb->len, 0, |
@@ -3297,7 +3446,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, | |||
3297 | 3446 | ||
3298 | /* no need to change probe response if the SSID is set correctly */ | 3447 | /* no need to change probe response if the SSID is set correctly */ |
3299 | if (wlvif->ssid_len > 0) | 3448 | if (wlvif->ssid_len > 0) |
3300 | return wl1271_cmd_template_set(wl, | 3449 | return wl1271_cmd_template_set(wl, wlvif->role_id, |
3301 | CMD_TEMPL_AP_PROBE_RESPONSE, | 3450 | CMD_TEMPL_AP_PROBE_RESPONSE, |
3302 | probe_rsp_data, | 3451 | probe_rsp_data, |
3303 | probe_rsp_len, 0, | 3452 | probe_rsp_len, 0, |
@@ -3334,7 +3483,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, | |||
3334 | ptr, probe_rsp_len - (ptr - probe_rsp_data)); | 3483 | ptr, probe_rsp_len - (ptr - probe_rsp_data)); |
3335 | templ_len += probe_rsp_len - (ptr - probe_rsp_data); | 3484 | templ_len += probe_rsp_len - (ptr - probe_rsp_data); |
3336 | 3485 | ||
3337 | return wl1271_cmd_template_set(wl, | 3486 | return wl1271_cmd_template_set(wl, wlvif->role_id, |
3338 | CMD_TEMPL_AP_PROBE_RESPONSE, | 3487 | CMD_TEMPL_AP_PROBE_RESPONSE, |
3339 | probe_rsp_templ, | 3488 | probe_rsp_templ, |
3340 | templ_len, 0, | 3489 | templ_len, 0, |
@@ -3431,7 +3580,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3431 | min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 3580 | min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
3432 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | 3581 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : |
3433 | CMD_TEMPL_BEACON; | 3582 | CMD_TEMPL_BEACON; |
3434 | ret = wl1271_cmd_template_set(wl, tmpl_id, | 3583 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, |
3435 | beacon->data, | 3584 | beacon->data, |
3436 | beacon->len, 0, | 3585 | beacon->len, 0, |
3437 | min_rate); | 3586 | min_rate); |
@@ -3470,7 +3619,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3470 | beacon->len, | 3619 | beacon->len, |
3471 | min_rate); | 3620 | min_rate); |
3472 | else | 3621 | else |
3473 | ret = wl1271_cmd_template_set(wl, | 3622 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, |
3474 | CMD_TEMPL_PROBE_RESPONSE, | 3623 | CMD_TEMPL_PROBE_RESPONSE, |
3475 | beacon->data, | 3624 | beacon->data, |
3476 | beacon->len, 0, | 3625 | beacon->len, 0, |
@@ -3634,7 +3783,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3634 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; | 3783 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; |
3635 | } | 3784 | } |
3636 | 3785 | ||
3637 | if (changed & BSS_CHANGED_BSSID) | 3786 | if (changed & BSS_CHANGED_BSSID && |
3787 | (is_ibss || bss_conf->assoc)) | ||
3638 | if (!is_zero_ether_addr(bss_conf->bssid)) { | 3788 | if (!is_zero_ether_addr(bss_conf->bssid)) { |
3639 | ret = wl12xx_cmd_build_null_data(wl, wlvif); | 3789 | ret = wl12xx_cmd_build_null_data(wl, wlvif); |
3640 | if (ret < 0) | 3790 | if (ret < 0) |
@@ -3673,8 +3823,6 @@ sta_not_found: | |||
3673 | wlvif->aid = bss_conf->aid; | 3823 | wlvif->aid = bss_conf->aid; |
3674 | set_assoc = true; | 3824 | set_assoc = true; |
3675 | 3825 | ||
3676 | wlvif->ps_poll_failures = 0; | ||
3677 | |||
3678 | /* | 3826 | /* |
3679 | * use basic rates from AP, and determine lowest rate | 3827 | * use basic rates from AP, and determine lowest rate |
3680 | * to use with control frames. | 3828 | * to use with control frames. |
@@ -3734,9 +3882,6 @@ sta_not_found: | |||
3734 | dev_kfree_skb(wlvif->probereq); | 3882 | dev_kfree_skb(wlvif->probereq); |
3735 | wlvif->probereq = NULL; | 3883 | wlvif->probereq = NULL; |
3736 | 3884 | ||
3737 | /* re-enable dynamic ps - just in case */ | ||
3738 | ieee80211_enable_dyn_ps(vif); | ||
3739 | |||
3740 | /* revert back to minimum rates for the current band */ | 3885 | /* revert back to minimum rates for the current band */ |
3741 | wl1271_set_band_rate(wl, wlvif); | 3886 | wl1271_set_band_rate(wl, wlvif); |
3742 | wlvif->basic_rate = | 3887 | wlvif->basic_rate = |
@@ -3810,34 +3955,6 @@ sta_not_found: | |||
3810 | if (ret < 0) | 3955 | if (ret < 0) |
3811 | goto out; | 3956 | goto out; |
3812 | 3957 | ||
3813 | if (changed & BSS_CHANGED_ARP_FILTER) { | ||
3814 | __be32 addr = bss_conf->arp_addr_list[0]; | ||
3815 | WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); | ||
3816 | |||
3817 | if (bss_conf->arp_addr_cnt == 1 && | ||
3818 | bss_conf->arp_filter_enabled) { | ||
3819 | /* | ||
3820 | * The template should have been configured only upon | ||
3821 | * association. however, it seems that the correct ip | ||
3822 | * isn't being set (when sending), so we have to | ||
3823 | * reconfigure the template upon every ip change. | ||
3824 | */ | ||
3825 | ret = wl1271_cmd_build_arp_rsp(wl, wlvif, addr); | ||
3826 | if (ret < 0) { | ||
3827 | wl1271_warning("build arp rsp failed: %d", ret); | ||
3828 | goto out; | ||
3829 | } | ||
3830 | |||
3831 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, | ||
3832 | ACX_ARP_FILTER_ARP_FILTERING, | ||
3833 | addr); | ||
3834 | } else | ||
3835 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); | ||
3836 | |||
3837 | if (ret < 0) | ||
3838 | goto out; | ||
3839 | } | ||
3840 | |||
3841 | if (do_join) { | 3958 | if (do_join) { |
3842 | ret = wl1271_join(wl, wlvif, set_assoc); | 3959 | ret = wl1271_join(wl, wlvif, set_assoc); |
3843 | if (ret < 0) { | 3960 | if (ret < 0) { |
@@ -3863,19 +3980,6 @@ sta_not_found: | |||
3863 | if (ret < 0) | 3980 | if (ret < 0) |
3864 | goto out; | 3981 | goto out; |
3865 | } | 3982 | } |
3866 | |||
3867 | /* If we want to go in PSM but we're not there yet */ | ||
3868 | if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && | ||
3869 | !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { | ||
3870 | enum wl1271_cmd_ps_mode mode; | ||
3871 | |||
3872 | mode = STATION_POWER_SAVE_MODE; | ||
3873 | ret = wl1271_ps_set_mode(wl, wlvif, mode, | ||
3874 | wlvif->basic_rate, | ||
3875 | true); | ||
3876 | if (ret < 0) | ||
3877 | goto out; | ||
3878 | } | ||
3879 | } | 3983 | } |
3880 | 3984 | ||
3881 | /* Handle new association with HT. Do this after join. */ | 3985 | /* Handle new association with HT. Do this after join. */ |
@@ -3917,6 +4021,41 @@ sta_not_found: | |||
3917 | } | 4021 | } |
3918 | } | 4022 | } |
3919 | 4023 | ||
4024 | /* Handle arp filtering. Done after join. */ | ||
4025 | if ((changed & BSS_CHANGED_ARP_FILTER) || | ||
4026 | (!is_ibss && (changed & BSS_CHANGED_QOS))) { | ||
4027 | __be32 addr = bss_conf->arp_addr_list[0]; | ||
4028 | wlvif->sta.qos = bss_conf->qos; | ||
4029 | WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); | ||
4030 | |||
4031 | if (bss_conf->arp_addr_cnt == 1 && | ||
4032 | bss_conf->arp_filter_enabled) { | ||
4033 | wlvif->ip_addr = addr; | ||
4034 | /* | ||
4035 | * The template should have been configured only upon | ||
4036 | * association. however, it seems that the correct ip | ||
4037 | * isn't being set (when sending), so we have to | ||
4038 | * reconfigure the template upon every ip change. | ||
4039 | */ | ||
4040 | ret = wl1271_cmd_build_arp_rsp(wl, wlvif); | ||
4041 | if (ret < 0) { | ||
4042 | wl1271_warning("build arp rsp failed: %d", ret); | ||
4043 | goto out; | ||
4044 | } | ||
4045 | |||
4046 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, | ||
4047 | (ACX_ARP_FILTER_ARP_FILTERING | | ||
4048 | ACX_ARP_FILTER_AUTO_ARP), | ||
4049 | addr); | ||
4050 | } else { | ||
4051 | wlvif->ip_addr = 0; | ||
4052 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); | ||
4053 | } | ||
4054 | |||
4055 | if (ret < 0) | ||
4056 | goto out; | ||
4057 | } | ||
4058 | |||
3920 | out: | 4059 | out: |
3921 | return; | 4060 | return; |
3922 | } | 4061 | } |
@@ -4012,6 +4151,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, | |||
4012 | { | 4151 | { |
4013 | 4152 | ||
4014 | struct wl1271 *wl = hw->priv; | 4153 | struct wl1271 *wl = hw->priv; |
4154 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4015 | u64 mactime = ULLONG_MAX; | 4155 | u64 mactime = ULLONG_MAX; |
4016 | int ret; | 4156 | int ret; |
4017 | 4157 | ||
@@ -4026,7 +4166,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, | |||
4026 | if (ret < 0) | 4166 | if (ret < 0) |
4027 | goto out; | 4167 | goto out; |
4028 | 4168 | ||
4029 | ret = wl1271_acx_tsf_info(wl, &mactime); | 4169 | ret = wl12xx_acx_tsf_info(wl, wlvif, &mactime); |
4030 | if (ret < 0) | 4170 | if (ret < 0) |
4031 | goto out_sleep; | 4171 | goto out_sleep; |
4032 | 4172 | ||
@@ -4373,7 +4513,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
4373 | 4513 | ||
4374 | /* TODO: change mac80211 to pass vif as param */ | 4514 | /* TODO: change mac80211 to pass vif as param */ |
4375 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 4515 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
4376 | ret = wl12xx_cmd_channel_switch(wl, ch_switch); | 4516 | ret = wl12xx_cmd_channel_switch(wl, wlvif, ch_switch); |
4377 | 4517 | ||
4378 | if (!ret) | 4518 | if (!ret) |
4379 | set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); | 4519 | set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); |
@@ -4467,6 +4607,7 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
4467 | /* mapping to indexes for wl1271_rates */ | 4607 | /* mapping to indexes for wl1271_rates */ |
4468 | static const u8 wl1271_rate_to_idx_2ghz[] = { | 4608 | static const u8 wl1271_rate_to_idx_2ghz[] = { |
4469 | /* MCS rates are used only with 11n */ | 4609 | /* MCS rates are used only with 11n */ |
4610 | 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
4470 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ | 4611 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ |
4471 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ | 4612 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ |
4472 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ | 4613 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ |
@@ -4588,6 +4729,7 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
4588 | /* mapping to indexes for wl1271_rates_5ghz */ | 4729 | /* mapping to indexes for wl1271_rates_5ghz */ |
4589 | static const u8 wl1271_rate_to_idx_5ghz[] = { | 4730 | static const u8 wl1271_rate_to_idx_5ghz[] = { |
4590 | /* MCS rates are used only with 11n */ | 4731 | /* MCS rates are used only with 11n */ |
4732 | 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
4591 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ | 4733 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ |
4592 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ | 4734 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ |
4593 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ | 4735 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ |
@@ -4828,13 +4970,120 @@ static struct bin_attribute fwlog_attr = { | |||
4828 | .read = wl1271_sysfs_read_fwlog, | 4970 | .read = wl1271_sysfs_read_fwlog, |
4829 | }; | 4971 | }; |
4830 | 4972 | ||
4973 | static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | ||
4974 | { | ||
4975 | bool supported = false; | ||
4976 | u8 major, minor; | ||
4977 | |||
4978 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
4979 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
4980 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); | ||
4981 | |||
4982 | /* in wl128x we have the MAC address if the PG is >= (2, 1) */ | ||
4983 | if (major > 2 || (major == 2 && minor >= 1)) | ||
4984 | supported = true; | ||
4985 | } else { | ||
4986 | major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
4987 | minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver); | ||
4988 | |||
4989 | /* in wl127x we have the MAC address if the PG is >= (3, 1) */ | ||
4990 | if (major == 3 && minor >= 1) | ||
4991 | supported = true; | ||
4992 | } | ||
4993 | |||
4994 | wl1271_debug(DEBUG_PROBE, | ||
4995 | "PG Ver major = %d minor = %d, MAC %s present", | ||
4996 | major, minor, supported ? "is" : "is not"); | ||
4997 | |||
4998 | return supported; | ||
4999 | } | ||
5000 | |||
5001 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | ||
5002 | u32 oui, u32 nic, int n) | ||
5003 | { | ||
5004 | int i; | ||
5005 | |||
5006 | wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d", | ||
5007 | oui, nic, n); | ||
5008 | |||
5009 | if (nic + n - 1 > 0xffffff) | ||
5010 | wl1271_warning("NIC part of the MAC address wraps around!"); | ||
5011 | |||
5012 | for (i = 0; i < n; i++) { | ||
5013 | wl->addresses[i].addr[0] = (u8)(oui >> 16); | ||
5014 | wl->addresses[i].addr[1] = (u8)(oui >> 8); | ||
5015 | wl->addresses[i].addr[2] = (u8) oui; | ||
5016 | wl->addresses[i].addr[3] = (u8)(nic >> 16); | ||
5017 | wl->addresses[i].addr[4] = (u8)(nic >> 8); | ||
5018 | wl->addresses[i].addr[5] = (u8) nic; | ||
5019 | nic++; | ||
5020 | } | ||
5021 | |||
5022 | wl->hw->wiphy->n_addresses = n; | ||
5023 | wl->hw->wiphy->addresses = wl->addresses; | ||
5024 | } | ||
5025 | |||
5026 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | ||
5027 | { | ||
5028 | u32 mac1, mac2; | ||
5029 | |||
5030 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); | ||
5031 | |||
5032 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | ||
5033 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | ||
5034 | |||
5035 | /* these are the two parts of the BD_ADDR */ | ||
5036 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | ||
5037 | ((mac1 & 0xff000000) >> 24); | ||
5038 | wl->fuse_nic_addr = mac1 & 0xffffff; | ||
5039 | |||
5040 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); | ||
5041 | } | ||
5042 | |||
5043 | static int wl12xx_get_hw_info(struct wl1271 *wl) | ||
5044 | { | ||
5045 | int ret; | ||
5046 | u32 die_info; | ||
5047 | |||
5048 | ret = wl12xx_set_power_on(wl); | ||
5049 | if (ret < 0) | ||
5050 | goto out; | ||
5051 | |||
5052 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); | ||
5053 | |||
5054 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
5055 | die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | ||
5056 | else | ||
5057 | die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | ||
5058 | |||
5059 | wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | ||
5060 | |||
5061 | if (!wl12xx_mac_in_fuse(wl)) { | ||
5062 | wl->fuse_oui_addr = 0; | ||
5063 | wl->fuse_nic_addr = 0; | ||
5064 | } else { | ||
5065 | wl12xx_get_fuse_mac(wl); | ||
5066 | } | ||
5067 | |||
5068 | wl1271_power_off(wl); | ||
5069 | out: | ||
5070 | return ret; | ||
5071 | } | ||
5072 | |||
4831 | static int wl1271_register_hw(struct wl1271 *wl) | 5073 | static int wl1271_register_hw(struct wl1271 *wl) |
4832 | { | 5074 | { |
4833 | int ret; | 5075 | int ret; |
5076 | u32 oui_addr = 0, nic_addr = 0; | ||
4834 | 5077 | ||
4835 | if (wl->mac80211_registered) | 5078 | if (wl->mac80211_registered) |
4836 | return 0; | 5079 | return 0; |
4837 | 5080 | ||
5081 | ret = wl12xx_get_hw_info(wl); | ||
5082 | if (ret < 0) { | ||
5083 | wl1271_error("couldn't get hw info"); | ||
5084 | goto out; | ||
5085 | } | ||
5086 | |||
4838 | ret = wl1271_fetch_nvs(wl); | 5087 | ret = wl1271_fetch_nvs(wl); |
4839 | if (ret == 0) { | 5088 | if (ret == 0) { |
4840 | /* NOTE: The wl->nvs->nvs element must be first, in | 5089 | /* NOTE: The wl->nvs->nvs element must be first, in |
@@ -4843,20 +5092,25 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
4843 | */ | 5092 | */ |
4844 | u8 *nvs_ptr = (u8 *)wl->nvs; | 5093 | u8 *nvs_ptr = (u8 *)wl->nvs; |
4845 | 5094 | ||
4846 | wl->mac_addr[0] = nvs_ptr[11]; | 5095 | oui_addr = |
4847 | wl->mac_addr[1] = nvs_ptr[10]; | 5096 | (nvs_ptr[11] << 16) + (nvs_ptr[10] << 8) + nvs_ptr[6]; |
4848 | wl->mac_addr[2] = nvs_ptr[6]; | 5097 | nic_addr = |
4849 | wl->mac_addr[3] = nvs_ptr[5]; | 5098 | (nvs_ptr[5] << 16) + (nvs_ptr[4] << 8) + nvs_ptr[3]; |
4850 | wl->mac_addr[4] = nvs_ptr[4]; | ||
4851 | wl->mac_addr[5] = nvs_ptr[3]; | ||
4852 | } | 5099 | } |
4853 | 5100 | ||
4854 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 5101 | /* if the MAC address is zeroed in the NVS derive from fuse */ |
5102 | if (oui_addr == 0 && nic_addr == 0) { | ||
5103 | oui_addr = wl->fuse_oui_addr; | ||
5104 | /* fuse has the BD_ADDR, the WLAN addresses are the next two */ | ||
5105 | nic_addr = wl->fuse_nic_addr + 1; | ||
5106 | } | ||
5107 | |||
5108 | wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2); | ||
4855 | 5109 | ||
4856 | ret = ieee80211_register_hw(wl->hw); | 5110 | ret = ieee80211_register_hw(wl->hw); |
4857 | if (ret < 0) { | 5111 | if (ret < 0) { |
4858 | wl1271_error("unable to register mac80211 hw: %d", ret); | 5112 | wl1271_error("unable to register mac80211 hw: %d", ret); |
4859 | return ret; | 5113 | goto out; |
4860 | } | 5114 | } |
4861 | 5115 | ||
4862 | wl->mac80211_registered = true; | 5116 | wl->mac80211_registered = true; |
@@ -4867,13 +5121,14 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
4867 | 5121 | ||
4868 | wl1271_notice("loaded"); | 5122 | wl1271_notice("loaded"); |
4869 | 5123 | ||
4870 | return 0; | 5124 | out: |
5125 | return ret; | ||
4871 | } | 5126 | } |
4872 | 5127 | ||
4873 | static void wl1271_unregister_hw(struct wl1271 *wl) | 5128 | static void wl1271_unregister_hw(struct wl1271 *wl) |
4874 | { | 5129 | { |
4875 | if (wl->state == WL1271_STATE_PLT) | 5130 | if (wl->plt) |
4876 | __wl1271_plt_stop(wl); | 5131 | wl1271_plt_stop(wl); |
4877 | 5132 | ||
4878 | unregister_netdevice_notifier(&wl1271_dev_notifier); | 5133 | unregister_netdevice_notifier(&wl1271_dev_notifier); |
4879 | ieee80211_unregister_hw(wl->hw); | 5134 | ieee80211_unregister_hw(wl->hw); |
@@ -4892,7 +5147,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4892 | }; | 5147 | }; |
4893 | 5148 | ||
4894 | /* The tx descriptor buffer and the TKIP space. */ | 5149 | /* The tx descriptor buffer and the TKIP space. */ |
4895 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 5150 | wl->hw->extra_tx_headroom = WL1271_EXTRA_SPACE_TKIP + |
4896 | sizeof(struct wl1271_tx_hw_descr); | 5151 | sizeof(struct wl1271_tx_hw_descr); |
4897 | 5152 | ||
4898 | /* unit us */ | 5153 | /* unit us */ |
@@ -4902,6 +5157,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4902 | 5157 | ||
4903 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 5158 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
4904 | IEEE80211_HW_SUPPORTS_PS | | 5159 | IEEE80211_HW_SUPPORTS_PS | |
5160 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | ||
4905 | IEEE80211_HW_SUPPORTS_UAPSD | | 5161 | IEEE80211_HW_SUPPORTS_UAPSD | |
4906 | IEEE80211_HW_HAS_RATE_CONTROL | | 5162 | IEEE80211_HW_HAS_RATE_CONTROL | |
4907 | IEEE80211_HW_CONNECTION_MONITOR | | 5163 | IEEE80211_HW_CONNECTION_MONITOR | |
@@ -4909,7 +5165,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4909 | IEEE80211_HW_SPECTRUM_MGMT | | 5165 | IEEE80211_HW_SPECTRUM_MGMT | |
4910 | IEEE80211_HW_AP_LINK_PS | | 5166 | IEEE80211_HW_AP_LINK_PS | |
4911 | IEEE80211_HW_AMPDU_AGGREGATION | | 5167 | IEEE80211_HW_AMPDU_AGGREGATION | |
4912 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW; | 5168 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | |
5169 | IEEE80211_HW_SCAN_WHILE_IDLE; | ||
4913 | 5170 | ||
4914 | wl->hw->wiphy->cipher_suites = cipher_suites; | 5171 | wl->hw->wiphy->cipher_suites = cipher_suites; |
4915 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 5172 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
@@ -4925,10 +5182,10 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4925 | * should be the maximum length possible for a template, without | 5182 | * should be the maximum length possible for a template, without |
4926 | * the IEEE80211 header of the template | 5183 | * the IEEE80211 header of the template |
4927 | */ | 5184 | */ |
4928 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - | 5185 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
4929 | sizeof(struct ieee80211_header); | 5186 | sizeof(struct ieee80211_header); |
4930 | 5187 | ||
4931 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - | 5188 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
4932 | sizeof(struct ieee80211_header); | 5189 | sizeof(struct ieee80211_header); |
4933 | 5190 | ||
4934 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 5191 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
@@ -5022,7 +5279,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5022 | wl->rx_counter = 0; | 5279 | wl->rx_counter = 0; |
5023 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 5280 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
5024 | wl->band = IEEE80211_BAND_2GHZ; | 5281 | wl->band = IEEE80211_BAND_2GHZ; |
5025 | wl->vif = NULL; | ||
5026 | wl->flags = 0; | 5282 | wl->flags = 0; |
5027 | wl->sg_enabled = true; | 5283 | wl->sg_enabled = true; |
5028 | wl->hw_pg_ver = -1; | 5284 | wl->hw_pg_ver = -1; |
@@ -5047,6 +5303,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5047 | spin_lock_init(&wl->wl_lock); | 5303 | spin_lock_init(&wl->wl_lock); |
5048 | 5304 | ||
5049 | wl->state = WL1271_STATE_OFF; | 5305 | wl->state = WL1271_STATE_OFF; |
5306 | wl->fw_type = WL12XX_FW_TYPE_NONE; | ||
5050 | mutex_init(&wl->mutex); | 5307 | mutex_init(&wl->mutex); |
5051 | 5308 | ||
5052 | /* Apply default driver configuration. */ | 5309 | /* Apply default driver configuration. */ |
@@ -5114,6 +5371,7 @@ static int wl1271_free_hw(struct wl1271 *wl) | |||
5114 | 5371 | ||
5115 | vfree(wl->fw); | 5372 | vfree(wl->fw); |
5116 | wl->fw = NULL; | 5373 | wl->fw = NULL; |
5374 | wl->fw_type = WL12XX_FW_TYPE_NONE; | ||
5117 | kfree(wl->nvs); | 5375 | kfree(wl->nvs); |
5118 | wl->nvs = NULL; | 5376 | wl->nvs = NULL; |
5119 | 5377 | ||
@@ -5300,7 +5558,7 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); | |||
5300 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); | 5558 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); |
5301 | 5559 | ||
5302 | module_param_named(fwlog, fwlog_param, charp, 0); | 5560 | module_param_named(fwlog, fwlog_param, charp, 0); |
5303 | MODULE_PARM_DESC(keymap, | 5561 | MODULE_PARM_DESC(fwlog, |
5304 | "FW logger options: continuous, ondemand, dbgpins or disable"); | 5562 | "FW logger options: continuous, ondemand, dbgpins or disable"); |
5305 | 5563 | ||
5306 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); | 5564 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index a2bdacdd7e1d..23d67501c50a 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -56,7 +56,7 @@ void wl1271_elp_work(struct work_struct *work) | |||
56 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 56 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
57 | goto out; | 57 | goto out; |
58 | 58 | ||
59 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && | 59 | if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && |
60 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) | 60 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) |
61 | goto out; | 61 | goto out; |
62 | } | 62 | } |
@@ -84,7 +84,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
84 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 84 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
85 | return; | 85 | return; |
86 | 86 | ||
87 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && | 87 | if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && |
88 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) | 88 | test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) |
89 | return; | 89 | return; |
90 | } | 90 | } |
@@ -160,28 +160,39 @@ out: | |||
160 | } | 160 | } |
161 | 161 | ||
162 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 162 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
163 | enum wl1271_cmd_ps_mode mode, u32 rates, bool send) | 163 | enum wl1271_cmd_ps_mode mode) |
164 | { | 164 | { |
165 | int ret; | 165 | int ret; |
166 | u16 timeout = wl->conf.conn.dynamic_ps_timeout; | ||
166 | 167 | ||
167 | switch (mode) { | 168 | switch (mode) { |
169 | case STATION_AUTO_PS_MODE: | ||
168 | case STATION_POWER_SAVE_MODE: | 170 | case STATION_POWER_SAVE_MODE: |
169 | wl1271_debug(DEBUG_PSM, "entering psm"); | 171 | wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)", |
172 | mode, timeout); | ||
170 | 173 | ||
171 | ret = wl1271_acx_wake_up_conditions(wl, wlvif); | 174 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
175 | wl->conf.conn.wake_up_event, | ||
176 | wl->conf.conn.listen_interval); | ||
172 | if (ret < 0) { | 177 | if (ret < 0) { |
173 | wl1271_error("couldn't set wake up conditions"); | 178 | wl1271_error("couldn't set wake up conditions"); |
174 | return ret; | 179 | return ret; |
175 | } | 180 | } |
176 | 181 | ||
177 | ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE); | 182 | ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout); |
178 | if (ret < 0) | 183 | if (ret < 0) |
179 | return ret; | 184 | return ret; |
180 | 185 | ||
181 | set_bit(WLVIF_FLAG_PSM, &wlvif->flags); | 186 | set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); |
187 | |||
188 | /* enable beacon early termination. Not relevant for 5GHz */ | ||
189 | if (wlvif->band == IEEE80211_BAND_2GHZ) { | ||
190 | ret = wl1271_acx_bet_enable(wl, wlvif, true); | ||
191 | if (ret < 0) | ||
192 | return ret; | ||
193 | } | ||
182 | break; | 194 | break; |
183 | case STATION_ACTIVE_MODE: | 195 | case STATION_ACTIVE_MODE: |
184 | default: | ||
185 | wl1271_debug(DEBUG_PSM, "leaving psm"); | 196 | wl1271_debug(DEBUG_PSM, "leaving psm"); |
186 | 197 | ||
187 | /* disable beacon early termination */ | 198 | /* disable beacon early termination */ |
@@ -191,12 +202,15 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
191 | return ret; | 202 | return ret; |
192 | } | 203 | } |
193 | 204 | ||
194 | ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); | 205 | ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0); |
195 | if (ret < 0) | 206 | if (ret < 0) |
196 | return ret; | 207 | return ret; |
197 | 208 | ||
198 | clear_bit(WLVIF_FLAG_PSM, &wlvif->flags); | 209 | clear_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); |
199 | break; | 210 | break; |
211 | default: | ||
212 | wl1271_warning("trying to set ps to unsupported mode %d", mode); | ||
213 | ret = -EINVAL; | ||
200 | } | 214 | } |
201 | 215 | ||
202 | return ret; | 216 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index a12052f02026..5f19d4fbbf27 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "acx.h" | 28 | #include "acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
31 | enum wl1271_cmd_ps_mode mode, u32 rates, bool send); | 31 | enum wl1271_cmd_ps_mode mode); |
32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl); |
34 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h index df34d5977b98..340db324bc26 100644 --- a/drivers/net/wireless/wl12xx/reg.h +++ b/drivers/net/wireless/wl12xx/reg.h | |||
@@ -525,4 +525,31 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
525 | */ | 525 | */ |
526 | #define INTR_TRIG_TX_PROC1 BIT(18) | 526 | #define INTR_TRIG_TX_PROC1 BIT(18) |
527 | 527 | ||
528 | #define WL127X_REG_FUSE_DATA_2_1 0x050a | ||
529 | #define WL128X_REG_FUSE_DATA_2_1 0x2152 | ||
530 | #define PG_VER_MASK 0x3c | ||
531 | #define PG_VER_OFFSET 2 | ||
532 | |||
533 | #define WL127X_PG_MAJOR_VER_MASK 0x3 | ||
534 | #define WL127X_PG_MAJOR_VER_OFFSET 0x0 | ||
535 | #define WL127X_PG_MINOR_VER_MASK 0xc | ||
536 | #define WL127X_PG_MINOR_VER_OFFSET 0x2 | ||
537 | |||
538 | #define WL128X_PG_MAJOR_VER_MASK 0xc | ||
539 | #define WL128X_PG_MAJOR_VER_OFFSET 0x2 | ||
540 | #define WL128X_PG_MINOR_VER_MASK 0x3 | ||
541 | #define WL128X_PG_MINOR_VER_OFFSET 0x0 | ||
542 | |||
543 | #define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \ | ||
544 | WL127X_PG_MAJOR_VER_OFFSET) | ||
545 | #define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \ | ||
546 | WL127X_PG_MINOR_VER_OFFSET) | ||
547 | #define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \ | ||
548 | WL128X_PG_MAJOR_VER_OFFSET) | ||
549 | #define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \ | ||
550 | WL128X_PG_MINOR_VER_OFFSET) | ||
551 | |||
552 | #define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4 | ||
553 | #define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8 | ||
554 | |||
528 | #endif | 555 | #endif |
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 4fbd2a722ffa..cfa6071704c5 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
113 | * In PLT mode we seem to get frames and mac80211 warns about them, | 113 | * In PLT mode we seem to get frames and mac80211 warns about them, |
114 | * workaround this by not retrieving them at all. | 114 | * workaround this by not retrieving them at all. |
115 | */ | 115 | */ |
116 | if (unlikely(wl->state == WL1271_STATE_PLT)) | 116 | if (unlikely(wl->plt)) |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | /* the data read starts with the descriptor */ | 119 | /* the data read starts with the descriptor */ |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index e24111ececc5..e43a6b2c1d91 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -38,7 +38,6 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
38 | struct ieee80211_vif *vif; | 38 | struct ieee80211_vif *vif; |
39 | struct wl12xx_vif *wlvif; | 39 | struct wl12xx_vif *wlvif; |
40 | int ret; | 40 | int ret; |
41 | bool is_sta, is_ibss; | ||
42 | 41 | ||
43 | dwork = container_of(work, struct delayed_work, work); | 42 | dwork = container_of(work, struct delayed_work, work); |
44 | wl = container_of(dwork, struct wl1271, scan_complete_work); | 43 | wl = container_of(dwork, struct wl1271, scan_complete_work); |
@@ -70,15 +69,6 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
70 | wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); | 69 | wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); |
71 | } | 70 | } |
72 | 71 | ||
73 | /* return to ROC if needed */ | ||
74 | is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); | ||
75 | is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); | ||
76 | if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) || | ||
77 | (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) && | ||
78 | !test_bit(wlvif->dev_role_id, wl->roc_map)) { | ||
79 | /* restore remain on channel */ | ||
80 | wl12xx_start_dev(wl, wlvif); | ||
81 | } | ||
82 | wl1271_ps_elp_sleep(wl); | 72 | wl1271_ps_elp_sleep(wl); |
83 | 73 | ||
84 | if (wl->scan.failed) { | 74 | if (wl->scan.failed) { |
@@ -182,14 +172,23 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, | |||
182 | goto out; | 172 | goto out; |
183 | } | 173 | } |
184 | 174 | ||
175 | if (wl->conf.scan.split_scan_timeout) | ||
176 | scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN; | ||
177 | |||
185 | if (passive) | 178 | if (passive) |
186 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | 179 | scan_options |= WL1271_SCAN_OPT_PASSIVE; |
187 | 180 | ||
188 | if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) { | 181 | if (wlvif->bss_type == BSS_TYPE_AP_BSS || |
182 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
183 | cmd->params.role_id = wlvif->role_id; | ||
184 | else | ||
185 | cmd->params.role_id = wlvif->dev_role_id; | ||
186 | |||
187 | if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { | ||
189 | ret = -EINVAL; | 188 | ret = -EINVAL; |
190 | goto out; | 189 | goto out; |
191 | } | 190 | } |
192 | cmd->params.role_id = wlvif->role_id; | 191 | |
193 | cmd->params.scan_options = cpu_to_le16(scan_options); | 192 | cmd->params.scan_options = cpu_to_le16(scan_options); |
194 | 193 | ||
195 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | 194 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, |
@@ -202,7 +201,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, | |||
202 | 201 | ||
203 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | 202 | cmd->params.tx_rate = cpu_to_le32(basic_rate); |
204 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; | 203 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; |
205 | cmd->params.tid_trigger = 0; | 204 | cmd->params.tid_trigger = CONF_TX_AC_ANY_TID; |
206 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 205 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
207 | 206 | ||
208 | if (band == IEEE80211_BAND_2GHZ) | 207 | if (band == IEEE80211_BAND_2GHZ) |
@@ -217,16 +216,17 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, | |||
217 | 216 | ||
218 | memcpy(cmd->addr, vif->addr, ETH_ALEN); | 217 | memcpy(cmd->addr, vif->addr, ETH_ALEN); |
219 | 218 | ||
220 | ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid, | 219 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, |
221 | wl->scan.ssid_len, wl->scan.req->ie, | 220 | cmd->params.role_id, band, |
222 | wl->scan.req->ie_len, band); | 221 | wl->scan.ssid, wl->scan.ssid_len, |
222 | wl->scan.req->ie, | ||
223 | wl->scan.req->ie_len); | ||
223 | if (ret < 0) { | 224 | if (ret < 0) { |
224 | wl1271_error("PROBE request template failed"); | 225 | wl1271_error("PROBE request template failed"); |
225 | goto out; | 226 | goto out; |
226 | } | 227 | } |
227 | 228 | ||
228 | /* disable the timeout */ | 229 | trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout); |
229 | trigger->timeout = 0; | ||
230 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | 230 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, |
231 | sizeof(*trigger), 0); | 231 | sizeof(*trigger), 0); |
232 | if (ret < 0) { | 232 | if (ret < 0) { |
@@ -658,11 +658,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
658 | } | 658 | } |
659 | 659 | ||
660 | if (!force_passive && cfg->active[0]) { | 660 | if (!force_passive && cfg->active[0]) { |
661 | ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, | 661 | u8 band = IEEE80211_BAND_2GHZ; |
662 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
663 | wlvif->dev_role_id, band, | ||
664 | req->ssids[0].ssid, | ||
662 | req->ssids[0].ssid_len, | 665 | req->ssids[0].ssid_len, |
663 | ies->ie[IEEE80211_BAND_2GHZ], | 666 | ies->ie[band], |
664 | ies->len[IEEE80211_BAND_2GHZ], | 667 | ies->len[band]); |
665 | IEEE80211_BAND_2GHZ); | ||
666 | if (ret < 0) { | 668 | if (ret < 0) { |
667 | wl1271_error("2.4GHz PROBE request template failed"); | 669 | wl1271_error("2.4GHz PROBE request template failed"); |
668 | goto out; | 670 | goto out; |
@@ -670,11 +672,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
670 | } | 672 | } |
671 | 673 | ||
672 | if (!force_passive && cfg->active[1]) { | 674 | if (!force_passive && cfg->active[1]) { |
673 | ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, | 675 | u8 band = IEEE80211_BAND_5GHZ; |
676 | ret = wl12xx_cmd_build_probe_req(wl, wlvif, | ||
677 | wlvif->dev_role_id, band, | ||
678 | req->ssids[0].ssid, | ||
674 | req->ssids[0].ssid_len, | 679 | req->ssids[0].ssid_len, |
675 | ies->ie[IEEE80211_BAND_5GHZ], | 680 | ies->ie[band], |
676 | ies->len[IEEE80211_BAND_5GHZ], | 681 | ies->len[band]); |
677 | IEEE80211_BAND_5GHZ); | ||
678 | if (ret < 0) { | 682 | if (ret < 0) { |
679 | wl1271_error("5GHz PROBE request template failed"); | 683 | wl1271_error("5GHz PROBE request template failed"); |
680 | goto out; | 684 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index a7ed43dc08c9..96ff457a3a0b 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h | |||
@@ -48,7 +48,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl); | |||
48 | #define WL1271_SCAN_CURRENT_TX_PWR 0 | 48 | #define WL1271_SCAN_CURRENT_TX_PWR 0 |
49 | #define WL1271_SCAN_OPT_ACTIVE 0 | 49 | #define WL1271_SCAN_OPT_ACTIVE 0 |
50 | #define WL1271_SCAN_OPT_PASSIVE 1 | 50 | #define WL1271_SCAN_OPT_PASSIVE 1 |
51 | #define WL1271_SCAN_OPT_TRIGGERED_SCAN 2 | 51 | #define WL1271_SCAN_OPT_SPLIT_SCAN 2 |
52 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | 52 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 |
53 | /* scan even if we fail to enter psm */ | 53 | /* scan even if we fail to enter psm */ |
54 | #define WL1271_SCAN_OPT_FORCE 8 | 54 | #define WL1271_SCAN_OPT_FORCE 8 |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 468a50553fac..4b3c32774bae 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -74,6 +74,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
74 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 74 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
75 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 75 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
76 | 76 | ||
77 | sdio_claim_host(func); | ||
78 | |||
77 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 79 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
78 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 80 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
79 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", | 81 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", |
@@ -88,6 +90,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
88 | addr, len); | 90 | addr, len); |
89 | } | 91 | } |
90 | 92 | ||
93 | sdio_release_host(func); | ||
94 | |||
91 | if (ret) | 95 | if (ret) |
92 | dev_err(child->parent, "sdio read failed (%d)\n", ret); | 96 | dev_err(child->parent, "sdio read failed (%d)\n", ret); |
93 | } | 97 | } |
@@ -99,6 +103,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
99 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 103 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
100 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 104 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
101 | 105 | ||
106 | sdio_claim_host(func); | ||
107 | |||
102 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 108 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
103 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 109 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
104 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", | 110 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", |
@@ -113,6 +119,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
113 | ret = sdio_memcpy_toio(func, addr, buf, len); | 119 | ret = sdio_memcpy_toio(func, addr, buf, len); |
114 | } | 120 | } |
115 | 121 | ||
122 | sdio_release_host(func); | ||
123 | |||
116 | if (ret) | 124 | if (ret) |
117 | dev_err(child->parent, "sdio write failed (%d)\n", ret); | 125 | dev_err(child->parent, "sdio write failed (%d)\n", ret); |
118 | } | 126 | } |
@@ -136,6 +144,7 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) | |||
136 | 144 | ||
137 | sdio_claim_host(func); | 145 | sdio_claim_host(func); |
138 | sdio_enable_func(func); | 146 | sdio_enable_func(func); |
147 | sdio_release_host(func); | ||
139 | 148 | ||
140 | out: | 149 | out: |
141 | return ret; | 150 | return ret; |
@@ -146,6 +155,7 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) | |||
146 | int ret; | 155 | int ret; |
147 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 156 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
148 | 157 | ||
158 | sdio_claim_host(func); | ||
149 | sdio_disable_func(func); | 159 | sdio_disable_func(func); |
150 | sdio_release_host(func); | 160 | sdio_release_host(func); |
151 | 161 | ||
@@ -314,9 +324,6 @@ static int wl1271_suspend(struct device *dev) | |||
314 | dev_err(dev, "error while trying to keep power\n"); | 324 | dev_err(dev, "error while trying to keep power\n"); |
315 | goto out; | 325 | goto out; |
316 | } | 326 | } |
317 | |||
318 | /* release host */ | ||
319 | sdio_release_host(func); | ||
320 | } | 327 | } |
321 | out: | 328 | out: |
322 | return ret; | 329 | return ret; |
@@ -324,15 +331,7 @@ out: | |||
324 | 331 | ||
325 | static int wl1271_resume(struct device *dev) | 332 | static int wl1271_resume(struct device *dev) |
326 | { | 333 | { |
327 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
328 | struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); | ||
329 | struct wl1271 *wl = platform_get_drvdata(glue->core); | ||
330 | |||
331 | dev_dbg(dev, "wl1271 resume\n"); | 334 | dev_dbg(dev, "wl1271 resume\n"); |
332 | if (wl->wow_enabled) { | ||
333 | /* claim back host */ | ||
334 | sdio_claim_host(func); | ||
335 | } | ||
336 | 335 | ||
337 | return 0; | 336 | return 0; |
338 | } | 337 | } |
@@ -371,5 +370,9 @@ module_exit(wl1271_exit); | |||
371 | MODULE_LICENSE("GPL"); | 370 | MODULE_LICENSE("GPL"); |
372 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 371 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
373 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 372 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
374 | MODULE_FIRMWARE(WL127X_FW_NAME); | 373 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
375 | MODULE_FIRMWARE(WL128X_FW_NAME); | 374 | MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); |
375 | MODULE_FIRMWARE(WL127X_PLT_FW_NAME); | ||
376 | MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); | ||
377 | MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); | ||
378 | MODULE_FIRMWARE(WL128X_PLT_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 92caa7ce6053..2fc18a8dcce8 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c | |||
@@ -433,6 +433,10 @@ module_exit(wl1271_exit); | |||
433 | MODULE_LICENSE("GPL"); | 433 | MODULE_LICENSE("GPL"); |
434 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 434 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
435 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 435 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
436 | MODULE_FIRMWARE(WL127X_FW_NAME); | 436 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
437 | MODULE_FIRMWARE(WL128X_FW_NAME); | 437 | MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); |
438 | MODULE_FIRMWARE(WL127X_PLT_FW_NAME); | ||
439 | MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); | ||
440 | MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); | ||
441 | MODULE_FIRMWARE(WL128X_PLT_FW_NAME); | ||
438 | MODULE_ALIAS("spi:wl1271"); | 442 | MODULE_ALIAS("spi:wl1271"); |
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 25093c0cb0ed..1e93bb9c0246 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "acx.h" | 30 | #include "acx.h" |
31 | #include "reg.h" | 31 | #include "reg.h" |
32 | #include "ps.h" | 32 | #include "ps.h" |
33 | #include "io.h" | ||
33 | 34 | ||
34 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | 35 | #define WL1271_TM_MAX_DATA_LENGTH 1024 |
35 | 36 | ||
@@ -41,6 +42,7 @@ enum wl1271_tm_commands { | |||
41 | WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ | 42 | WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ |
42 | WL1271_TM_CMD_SET_PLT_MODE, | 43 | WL1271_TM_CMD_SET_PLT_MODE, |
43 | WL1271_TM_CMD_RECOVER, | 44 | WL1271_TM_CMD_RECOVER, |
45 | WL1271_TM_CMD_GET_MAC, | ||
44 | 46 | ||
45 | __WL1271_TM_CMD_AFTER_LAST | 47 | __WL1271_TM_CMD_AFTER_LAST |
46 | }; | 48 | }; |
@@ -264,6 +266,52 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) | |||
264 | return 0; | 266 | return 0; |
265 | } | 267 | } |
266 | 268 | ||
269 | static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) | ||
270 | { | ||
271 | struct sk_buff *skb; | ||
272 | u8 mac_addr[ETH_ALEN]; | ||
273 | int ret = 0; | ||
274 | |||
275 | mutex_lock(&wl->mutex); | ||
276 | |||
277 | if (!wl->plt) { | ||
278 | ret = -EINVAL; | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | if (wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) { | ||
283 | ret = -EOPNOTSUPP; | ||
284 | goto out; | ||
285 | } | ||
286 | |||
287 | mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16); | ||
288 | mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8); | ||
289 | mac_addr[2] = (u8) wl->fuse_oui_addr; | ||
290 | mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16); | ||
291 | mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8); | ||
292 | mac_addr[5] = (u8) wl->fuse_nic_addr; | ||
293 | |||
294 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN); | ||
295 | if (!skb) { | ||
296 | ret = -ENOMEM; | ||
297 | goto out; | ||
298 | } | ||
299 | |||
300 | NLA_PUT(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr); | ||
301 | ret = cfg80211_testmode_reply(skb); | ||
302 | if (ret < 0) | ||
303 | goto out; | ||
304 | |||
305 | out: | ||
306 | mutex_unlock(&wl->mutex); | ||
307 | return ret; | ||
308 | |||
309 | nla_put_failure: | ||
310 | kfree_skb(skb); | ||
311 | ret = -EMSGSIZE; | ||
312 | goto out; | ||
313 | } | ||
314 | |||
267 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) | 315 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) |
268 | { | 316 | { |
269 | struct wl1271 *wl = hw->priv; | 317 | struct wl1271 *wl = hw->priv; |
@@ -288,6 +336,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) | |||
288 | return wl1271_tm_cmd_set_plt_mode(wl, tb); | 336 | return wl1271_tm_cmd_set_plt_mode(wl, tb); |
289 | case WL1271_TM_CMD_RECOVER: | 337 | case WL1271_TM_CMD_RECOVER: |
290 | return wl1271_tm_cmd_recover(wl, tb); | 338 | return wl1271_tm_cmd_recover(wl, tb); |
339 | case WL1271_TM_CMD_GET_MAC: | ||
340 | return wl12xx_tm_cmd_get_mac(wl, tb); | ||
291 | default: | 341 | default: |
292 | return -EOPNOTSUPP; | 342 | return -EOPNOTSUPP; |
293 | } | 343 | } |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 4508ccd78328..6446e4d3e8f9 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -77,35 +77,6 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) | |||
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | static int wl1271_tx_update_filters(struct wl1271 *wl, | ||
81 | struct wl12xx_vif *wlvif, | ||
82 | struct sk_buff *skb) | ||
83 | { | ||
84 | struct ieee80211_hdr *hdr; | ||
85 | int ret; | ||
86 | |||
87 | hdr = (struct ieee80211_hdr *)skb->data; | ||
88 | |||
89 | /* | ||
90 | * stop bssid-based filtering before transmitting authentication | ||
91 | * requests. this way the hw will never drop authentication | ||
92 | * responses coming from BSSIDs it isn't familiar with (e.g. on | ||
93 | * roaming) | ||
94 | */ | ||
95 | if (!ieee80211_is_auth(hdr->frame_control)) | ||
96 | return 0; | ||
97 | |||
98 | if (wlvif->dev_hlid != WL12XX_INVALID_LINK_ID) | ||
99 | goto out; | ||
100 | |||
101 | wl1271_debug(DEBUG_CMD, "starting device role for roaming"); | ||
102 | ret = wl12xx_start_dev(wl, wlvif); | ||
103 | if (ret < 0) | ||
104 | goto out; | ||
105 | out: | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, | 80 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, |
110 | struct sk_buff *skb) | 81 | struct sk_buff *skb) |
111 | { | 82 | { |
@@ -187,8 +158,6 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
187 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 158 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
188 | return wl12xx_tx_get_hlid_ap(wl, wlvif, skb); | 159 | return wl12xx_tx_get_hlid_ap(wl, wlvif, skb); |
189 | 160 | ||
190 | wl1271_tx_update_filters(wl, wlvif, skb); | ||
191 | |||
192 | if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || | 161 | if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || |
193 | test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && | 162 | test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && |
194 | !ieee80211_is_auth(hdr->frame_control) && | 163 | !ieee80211_is_auth(hdr->frame_control) && |
@@ -286,16 +255,20 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
286 | int aligned_len, ac, rate_idx; | 255 | int aligned_len, ac, rate_idx; |
287 | s64 hosttime; | 256 | s64 hosttime; |
288 | u16 tx_attr = 0; | 257 | u16 tx_attr = 0; |
258 | __le16 frame_control; | ||
259 | struct ieee80211_hdr *hdr; | ||
260 | u8 *frame_start; | ||
289 | bool is_dummy; | 261 | bool is_dummy; |
290 | 262 | ||
291 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 263 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
264 | frame_start = (u8 *)(desc + 1); | ||
265 | hdr = (struct ieee80211_hdr *)(frame_start + extra); | ||
266 | frame_control = hdr->frame_control; | ||
292 | 267 | ||
293 | /* relocate space for security header */ | 268 | /* relocate space for security header */ |
294 | if (extra) { | 269 | if (extra) { |
295 | void *framestart = skb->data + sizeof(*desc); | 270 | int hdrlen = ieee80211_hdrlen(frame_control); |
296 | u16 fc = *(u16 *)(framestart + extra); | 271 | memmove(frame_start, hdr, hdrlen); |
297 | int hdrlen = ieee80211_hdrlen(cpu_to_le16(fc)); | ||
298 | memmove(framestart, framestart + extra, hdrlen); | ||
299 | } | 272 | } |
300 | 273 | ||
301 | /* configure packet life time */ | 274 | /* configure packet life time */ |
@@ -384,6 +357,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
384 | desc->wl127x_mem.total_mem_blocks); | 357 | desc->wl127x_mem.total_mem_blocks); |
385 | } | 358 | } |
386 | 359 | ||
360 | /* for WEP shared auth - no fw encryption is needed */ | ||
361 | if (ieee80211_is_auth(frame_control) && | ||
362 | ieee80211_has_protected(frame_control)) | ||
363 | tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; | ||
364 | |||
387 | desc->tx_attr = cpu_to_le16(tx_attr); | 365 | desc->tx_attr = cpu_to_le16(tx_attr); |
388 | } | 366 | } |
389 | 367 | ||
@@ -408,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
408 | 386 | ||
409 | if (info->control.hw_key && | 387 | if (info->control.hw_key && |
410 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) | 388 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) |
411 | extra = WL1271_TKIP_IV_SPACE; | 389 | extra = WL1271_EXTRA_SPACE_TKIP; |
412 | 390 | ||
413 | if (info->control.hw_key) { | 391 | if (info->control.hw_key) { |
414 | bool is_wep; | 392 | bool is_wep; |
@@ -795,6 +773,18 @@ out: | |||
795 | mutex_unlock(&wl->mutex); | 773 | mutex_unlock(&wl->mutex); |
796 | } | 774 | } |
797 | 775 | ||
776 | static u8 wl1271_tx_get_rate_flags(u8 rate_class_index) | ||
777 | { | ||
778 | u8 flags = 0; | ||
779 | |||
780 | if (rate_class_index >= CONF_HW_RXTX_RATE_MCS_MIN && | ||
781 | rate_class_index <= CONF_HW_RXTX_RATE_MCS_MAX) | ||
782 | flags |= IEEE80211_TX_RC_MCS; | ||
783 | if (rate_class_index == CONF_HW_RXTX_RATE_MCS7_SGI) | ||
784 | flags |= IEEE80211_TX_RC_SHORT_GI; | ||
785 | return flags; | ||
786 | } | ||
787 | |||
798 | static void wl1271_tx_complete_packet(struct wl1271 *wl, | 788 | static void wl1271_tx_complete_packet(struct wl1271 *wl, |
799 | struct wl1271_tx_hw_res_descr *result) | 789 | struct wl1271_tx_hw_res_descr *result) |
800 | { | 790 | { |
@@ -804,6 +794,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
804 | struct sk_buff *skb; | 794 | struct sk_buff *skb; |
805 | int id = result->id; | 795 | int id = result->id; |
806 | int rate = -1; | 796 | int rate = -1; |
797 | u8 rate_flags = 0; | ||
807 | u8 retries = 0; | 798 | u8 retries = 0; |
808 | 799 | ||
809 | /* check for id legality */ | 800 | /* check for id legality */ |
@@ -830,6 +821,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
830 | info->flags |= IEEE80211_TX_STAT_ACK; | 821 | info->flags |= IEEE80211_TX_STAT_ACK; |
831 | rate = wl1271_rate_to_idx(result->rate_class_index, | 822 | rate = wl1271_rate_to_idx(result->rate_class_index, |
832 | wlvif->band); | 823 | wlvif->band); |
824 | rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index); | ||
833 | retries = result->ack_failures; | 825 | retries = result->ack_failures; |
834 | } else if (result->status == TX_RETRY_EXCEEDED) { | 826 | } else if (result->status == TX_RETRY_EXCEEDED) { |
835 | wl->stats.excessive_retries++; | 827 | wl->stats.excessive_retries++; |
@@ -838,7 +830,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
838 | 830 | ||
839 | info->status.rates[0].idx = rate; | 831 | info->status.rates[0].idx = rate; |
840 | info->status.rates[0].count = retries; | 832 | info->status.rates[0].count = retries; |
841 | info->status.rates[0].flags = 0; | 833 | info->status.rates[0].flags = rate_flags; |
842 | info->status.ack_signal = -1; | 834 | info->status.ack_signal = -1; |
843 | 835 | ||
844 | wl->stats.retry_count += result->ack_failures; | 836 | wl->stats.retry_count += result->ack_failures; |
@@ -869,8 +861,9 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
869 | if (info->control.hw_key && | 861 | if (info->control.hw_key && |
870 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { | 862 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
871 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 863 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
872 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); | 864 | memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, |
873 | skb_pull(skb, WL1271_TKIP_IV_SPACE); | 865 | hdrlen); |
866 | skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); | ||
874 | } | 867 | } |
875 | 868 | ||
876 | wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" | 869 | wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" |
@@ -1012,9 +1005,9 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
1012 | info->control.hw_key->cipher == | 1005 | info->control.hw_key->cipher == |
1013 | WLAN_CIPHER_SUITE_TKIP) { | 1006 | WLAN_CIPHER_SUITE_TKIP) { |
1014 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1007 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1015 | memmove(skb->data + WL1271_TKIP_IV_SPACE, | 1008 | memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, |
1016 | skb->data, hdrlen); | 1009 | skb->data, hdrlen); |
1017 | skb_pull(skb, WL1271_TKIP_IV_SPACE); | 1010 | skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); |
1018 | } | 1011 | } |
1019 | 1012 | ||
1020 | info->status.rates[0].idx = -1; | 1013 | info->status.rates[0].idx = -1; |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 2dbb24e6d541..e3977b55a710 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) | 39 | #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) |
40 | #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) | 40 | #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) |
41 | #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) | 41 | #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) |
42 | #define TX_HW_ATTR_HOST_ENCRYPT BIT(14) | ||
42 | 43 | ||
43 | #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 | 44 | #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 |
44 | #define TX_HW_ATTR_OFST_HEADER_PAD 1 | 45 | #define TX_HW_ATTR_OFST_HEADER_PAD 1 |
@@ -51,7 +52,9 @@ | |||
51 | #define TX_HW_RESULT_QUEUE_LEN_MASK 0xf | 52 | #define TX_HW_RESULT_QUEUE_LEN_MASK 0xf |
52 | 53 | ||
53 | #define WL1271_TX_ALIGN_TO 4 | 54 | #define WL1271_TX_ALIGN_TO 4 |
54 | #define WL1271_TKIP_IV_SPACE 4 | 55 | #define WL1271_EXTRA_SPACE_TKIP 4 |
56 | #define WL1271_EXTRA_SPACE_AES 8 | ||
57 | #define WL1271_EXTRA_SPACE_MAX 8 | ||
55 | 58 | ||
56 | /* Used for management frames and dummy packets */ | 59 | /* Used for management frames and dummy packets */ |
57 | #define WL1271_TID_MGMT 7 | 60 | #define WL1271_TID_MGMT 7 |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b2b09cd02022..90352415e2aa 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -35,8 +35,14 @@ | |||
35 | #include "conf.h" | 35 | #include "conf.h" |
36 | #include "ini.h" | 36 | #include "ini.h" |
37 | 37 | ||
38 | #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" | 38 | #define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" |
39 | #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" | 39 | #define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" |
40 | |||
41 | #define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" | ||
42 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" | ||
43 | |||
44 | #define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" | ||
45 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" | ||
40 | 46 | ||
41 | /* | 47 | /* |
42 | * wl127x and wl128x are using the same NVS file name. However, the | 48 | * wl127x and wl128x are using the same NVS file name. However, the |
@@ -90,7 +96,13 @@ | |||
90 | enum wl1271_state { | 96 | enum wl1271_state { |
91 | WL1271_STATE_OFF, | 97 | WL1271_STATE_OFF, |
92 | WL1271_STATE_ON, | 98 | WL1271_STATE_ON, |
93 | WL1271_STATE_PLT, | 99 | }; |
100 | |||
101 | enum wl12xx_fw_type { | ||
102 | WL12XX_FW_TYPE_NONE, | ||
103 | WL12XX_FW_TYPE_NORMAL, | ||
104 | WL12XX_FW_TYPE_MULTI, | ||
105 | WL12XX_FW_TYPE_PLT, | ||
94 | }; | 106 | }; |
95 | 107 | ||
96 | enum wl1271_partition_type { | 108 | enum wl1271_partition_type { |
@@ -247,6 +259,7 @@ enum wl12xx_flags { | |||
247 | WL1271_FLAG_PENDING_WORK, | 259 | WL1271_FLAG_PENDING_WORK, |
248 | WL1271_FLAG_SOFT_GEMINI, | 260 | WL1271_FLAG_SOFT_GEMINI, |
249 | WL1271_FLAG_RECOVERY_IN_PROGRESS, | 261 | WL1271_FLAG_RECOVERY_IN_PROGRESS, |
262 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, | ||
250 | }; | 263 | }; |
251 | 264 | ||
252 | enum wl12xx_vif_flags { | 265 | enum wl12xx_vif_flags { |
@@ -254,8 +267,7 @@ enum wl12xx_vif_flags { | |||
254 | WLVIF_FLAG_STA_ASSOCIATED, | 267 | WLVIF_FLAG_STA_ASSOCIATED, |
255 | WLVIF_FLAG_IBSS_JOINED, | 268 | WLVIF_FLAG_IBSS_JOINED, |
256 | WLVIF_FLAG_AP_STARTED, | 269 | WLVIF_FLAG_AP_STARTED, |
257 | WLVIF_FLAG_PSM, | 270 | WLVIF_FLAG_IN_PS, |
258 | WLVIF_FLAG_PSM_REQUESTED, | ||
259 | WLVIF_FLAG_STA_STATE_SENT, | 271 | WLVIF_FLAG_STA_STATE_SENT, |
260 | WLVIF_FLAG_RX_STREAMING_STARTED, | 272 | WLVIF_FLAG_RX_STREAMING_STARTED, |
261 | WLVIF_FLAG_PSPOLL_FAILURE, | 273 | WLVIF_FLAG_PSPOLL_FAILURE, |
@@ -295,6 +307,9 @@ struct wl1271 { | |||
295 | spinlock_t wl_lock; | 307 | spinlock_t wl_lock; |
296 | 308 | ||
297 | enum wl1271_state state; | 309 | enum wl1271_state state; |
310 | enum wl12xx_fw_type fw_type; | ||
311 | bool plt; | ||
312 | u8 last_vif_count; | ||
298 | struct mutex mutex; | 313 | struct mutex mutex; |
299 | 314 | ||
300 | unsigned long flags; | 315 | unsigned long flags; |
@@ -313,7 +328,12 @@ struct wl1271 { | |||
313 | 328 | ||
314 | s8 hw_pg_ver; | 329 | s8 hw_pg_ver; |
315 | 330 | ||
316 | u8 mac_addr[ETH_ALEN]; | 331 | /* address read from the fuse ROM */ |
332 | u32 fuse_oui_addr; | ||
333 | u32 fuse_nic_addr; | ||
334 | |||
335 | /* we have up to 2 MAC addresses */ | ||
336 | struct mac_address addresses[2]; | ||
317 | int channel; | 337 | int channel; |
318 | u8 system_hlid; | 338 | u8 system_hlid; |
319 | 339 | ||
@@ -425,8 +445,6 @@ struct wl1271 { | |||
425 | struct wl12xx_fw_status *fw_status; | 445 | struct wl12xx_fw_status *fw_status; |
426 | struct wl1271_tx_hw_res_if *tx_res_if; | 446 | struct wl1271_tx_hw_res_if *tx_res_if; |
427 | 447 | ||
428 | struct ieee80211_vif *vif; | ||
429 | |||
430 | /* Current chipset configuration */ | 448 | /* Current chipset configuration */ |
431 | struct conf_drv_settings conf; | 449 | struct conf_drv_settings conf; |
432 | 450 | ||
@@ -503,6 +521,8 @@ struct wl12xx_vif { | |||
503 | u8 basic_rate_idx; | 521 | u8 basic_rate_idx; |
504 | u8 ap_rate_idx; | 522 | u8 ap_rate_idx; |
505 | u8 p2p_rate_idx; | 523 | u8 p2p_rate_idx; |
524 | |||
525 | bool qos; | ||
506 | } sta; | 526 | } sta; |
507 | struct { | 527 | struct { |
508 | u8 global_hlid; | 528 | u8 global_hlid; |
@@ -560,12 +580,6 @@ struct wl12xx_vif { | |||
560 | /* Session counter for the chipset */ | 580 | /* Session counter for the chipset */ |
561 | int session_counter; | 581 | int session_counter; |
562 | 582 | ||
563 | struct completion *ps_compl; | ||
564 | struct delayed_work pspoll_work; | ||
565 | |||
566 | /* counter for ps-poll delivery failures */ | ||
567 | int ps_poll_failures; | ||
568 | |||
569 | /* retry counter for PSM entries */ | 583 | /* retry counter for PSM entries */ |
570 | u8 psm_entry_retry; | 584 | u8 psm_entry_retry; |
571 | 585 | ||
@@ -575,6 +589,10 @@ struct wl12xx_vif { | |||
575 | int rssi_thold; | 589 | int rssi_thold; |
576 | int last_rssi_event; | 590 | int last_rssi_event; |
577 | 591 | ||
592 | /* save the current encryption type for auto-arp config */ | ||
593 | u8 encryption_type; | ||
594 | __be32 ip_addr; | ||
595 | |||
578 | /* RX BA constraint value */ | 596 | /* RX BA constraint value */ |
579 | bool ba_support; | 597 | bool ba_support; |
580 | bool ba_allowed; | 598 | bool ba_allowed; |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index 8f0ffaf62309..22b0bc98d7b5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h | |||
@@ -117,7 +117,7 @@ struct wl12xx_ps_poll_template { | |||
117 | } __packed; | 117 | } __packed; |
118 | 118 | ||
119 | struct wl12xx_arp_rsp_template { | 119 | struct wl12xx_arp_rsp_template { |
120 | struct ieee80211_hdr_3addr hdr; | 120 | /* not including ieee80211 header */ |
121 | 121 | ||
122 | u8 llc_hdr[sizeof(rfc1042_header)]; | 122 | u8 llc_hdr[sizeof(rfc1042_header)]; |
123 | __be16 llc_type; | 123 | __be16 llc_type; |