diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx')
35 files changed, 2765 insertions, 1431 deletions
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 785e0244e305..337fc7bec5a5 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -51,3 +51,27 @@ config WL1271 | |||
51 | 51 | ||
52 | If you choose to build a module, it'll be called wl1271. Say N if | 52 | If you choose to build a module, it'll be called wl1271. Say N if |
53 | unsure. | 53 | unsure. |
54 | |||
55 | config WL1271_SPI | ||
56 | tristate "TI wl1271 SPI support" | ||
57 | depends on WL1271 && SPI_MASTER | ||
58 | ---help--- | ||
59 | This module adds support for the SPI interface of adapters using | ||
60 | TI wl1271 chipset. Select this if your platform is using | ||
61 | the SPI bus. | ||
62 | |||
63 | If you choose to build a module, it'll be called wl1251_spi. | ||
64 | Say N if unsure. | ||
65 | |||
66 | config WL1271_SDIO | ||
67 | tristate "TI wl1271 SDIO support" | ||
68 | depends on WL1271 && MMC && ARM | ||
69 | ---help--- | ||
70 | This module adds support for the SDIO interface of adapters using | ||
71 | TI wl1271 chipset. Select this if your platform is using | ||
72 | the SDIO bus. | ||
73 | |||
74 | If you choose to build a module, it'll be called | ||
75 | wl1271_sdio. Say N if unsure. | ||
76 | |||
77 | |||
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index f47ec94c16dc..27ddd2be0a91 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -7,10 +7,12 @@ 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 | 9 | ||
10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o wl1271_io.o | 13 | wl1271_init.o wl1271_debugfs.o |
14 | 14 | ||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | 15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o |
16 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
17 | obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o | ||
18 | obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 37c61c19cae5..4f5f02a26e62 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -256,6 +256,8 @@ struct wl1251_debugfs { | |||
256 | struct wl1251_if_operations { | 256 | struct wl1251_if_operations { |
257 | void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); | 257 | void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); |
258 | void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); | 258 | void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); |
259 | void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); | ||
260 | void (*write_elp)(struct wl1251 *wl, int addr, u32 val); | ||
259 | void (*reset)(struct wl1251 *wl); | 261 | void (*reset)(struct wl1251 *wl); |
260 | void (*enable_irq)(struct wl1251 *wl); | 262 | void (*enable_irq)(struct wl1251 *wl); |
261 | void (*disable_irq)(struct wl1251 *wl); | 263 | void (*disable_irq)(struct wl1251 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index d5ac79aeaa73..2545123931e8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -497,7 +497,8 @@ int wl1251_boot(struct wl1251 *wl) | |||
497 | /* 2. start processing NVS file */ | 497 | /* 2. start processing NVS file */ |
498 | if (wl->use_eeprom) { | 498 | if (wl->use_eeprom) { |
499 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); | 499 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); |
500 | msleep(4000); | 500 | /* Wait for EEPROM NVS burst read to complete */ |
501 | msleep(40); | ||
501 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | 502 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); |
502 | } else { | 503 | } else { |
503 | ret = wl1251_boot_upload_nvs(wl); | 504 | ret = wl1251_boot_upload_nvs(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h index b89d2ac62efb..c545e9d5f512 100644 --- a/drivers/net/wireless/wl12xx/wl1251_io.h +++ b/drivers/net/wireless/wl12xx/wl1251_io.h | |||
@@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) | |||
48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | 48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); |
49 | } | 49 | } |
50 | 50 | ||
51 | static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) | ||
52 | { | ||
53 | u32 response; | ||
54 | |||
55 | if (wl->if_ops->read_elp) | ||
56 | wl->if_ops->read_elp(wl, addr, &response); | ||
57 | else | ||
58 | wl->if_ops->read(wl, addr, &response, sizeof(u32)); | ||
59 | |||
60 | return response; | ||
61 | } | ||
62 | |||
63 | static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
64 | { | ||
65 | if (wl->if_ops->write_elp) | ||
66 | wl->if_ops->write_elp(wl, addr, val); | ||
67 | else | ||
68 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | ||
69 | } | ||
70 | |||
51 | /* Memory target IO, address is translated to partition 0 */ | 71 | /* Memory target IO, address is translated to partition 0 */ |
52 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); | 72 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); |
53 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); | 73 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 1c8226eee409..00b24282fc73 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -147,8 +147,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) | |||
147 | u32 elp_reg; | 147 | u32 elp_reg; |
148 | 148 | ||
149 | elp_reg = ELPCTRL_WAKE_UP; | 149 | elp_reg = ELPCTRL_WAKE_UP; |
150 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | 150 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); |
151 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 151 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
152 | 152 | ||
153 | if (!(elp_reg & ELPCTRL_WLAN_READY)) | 153 | if (!(elp_reg & ELPCTRL_WLAN_READY)) |
154 | wl1251_warning("WLAN not ready"); | 154 | wl1251_warning("WLAN not ready"); |
@@ -202,8 +202,8 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
202 | goto out; | 202 | goto out; |
203 | } | 203 | } |
204 | 204 | ||
205 | /* No NVS from netlink, try to get it from the filesystem */ | 205 | if (wl->nvs == NULL && !wl->use_eeprom) { |
206 | if (wl->nvs == NULL) { | 206 | /* No NVS from netlink, try to get it from the filesystem */ |
207 | ret = wl1251_fetch_nvs(wl); | 207 | ret = wl1251_fetch_nvs(wl); |
208 | if (ret < 0) | 208 | if (ret < 0) |
209 | goto out; | 209 | goto out; |
@@ -857,6 +857,7 @@ out: | |||
857 | } | 857 | } |
858 | 858 | ||
859 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | 859 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, |
860 | struct ieee80211_vif *vif, | ||
860 | struct cfg80211_scan_request *req) | 861 | struct cfg80211_scan_request *req) |
861 | { | 862 | { |
862 | struct wl1251 *wl = hw->priv; | 863 | struct wl1251 *wl = hw->priv; |
@@ -1196,6 +1197,66 @@ static const struct ieee80211_ops wl1251_ops = { | |||
1196 | .conf_tx = wl1251_op_conf_tx, | 1197 | .conf_tx = wl1251_op_conf_tx, |
1197 | }; | 1198 | }; |
1198 | 1199 | ||
1200 | static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data) | ||
1201 | { | ||
1202 | unsigned long timeout; | ||
1203 | |||
1204 | wl1251_reg_write32(wl, EE_ADDR, offset); | ||
1205 | wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ); | ||
1206 | |||
1207 | /* EE_CTL_READ clears when data is ready */ | ||
1208 | timeout = jiffies + msecs_to_jiffies(100); | ||
1209 | while (1) { | ||
1210 | if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ)) | ||
1211 | break; | ||
1212 | |||
1213 | if (time_after(jiffies, timeout)) | ||
1214 | return -ETIMEDOUT; | ||
1215 | |||
1216 | msleep(1); | ||
1217 | } | ||
1218 | |||
1219 | *data = wl1251_reg_read32(wl, EE_DATA); | ||
1220 | return 0; | ||
1221 | } | ||
1222 | |||
1223 | static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset, | ||
1224 | u8 *data, size_t len) | ||
1225 | { | ||
1226 | size_t i; | ||
1227 | int ret; | ||
1228 | |||
1229 | wl1251_reg_write32(wl, EE_START, 0); | ||
1230 | |||
1231 | for (i = 0; i < len; i++) { | ||
1232 | ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]); | ||
1233 | if (ret < 0) | ||
1234 | return ret; | ||
1235 | } | ||
1236 | |||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | static int wl1251_read_eeprom_mac(struct wl1251 *wl) | ||
1241 | { | ||
1242 | u8 mac[ETH_ALEN]; | ||
1243 | int i, ret; | ||
1244 | |||
1245 | wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE); | ||
1246 | |||
1247 | ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac)); | ||
1248 | if (ret < 0) { | ||
1249 | wl1251_warning("failed to read MAC address from EEPROM"); | ||
1250 | return ret; | ||
1251 | } | ||
1252 | |||
1253 | /* MAC is stored in reverse order */ | ||
1254 | for (i = 0; i < ETH_ALEN; i++) | ||
1255 | wl->mac_addr[i] = mac[ETH_ALEN - i - 1]; | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1199 | static int wl1251_register_hw(struct wl1251 *wl) | 1260 | static int wl1251_register_hw(struct wl1251 *wl) |
1200 | { | 1261 | { |
1201 | int ret; | 1262 | int ret; |
@@ -1231,7 +1292,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1231 | wl->hw->channel_change_time = 10000; | 1292 | wl->hw->channel_change_time = 10000; |
1232 | 1293 | ||
1233 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1294 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1234 | IEEE80211_HW_NOISE_DBM | | ||
1235 | IEEE80211_HW_SUPPORTS_PS | | 1295 | IEEE80211_HW_SUPPORTS_PS | |
1236 | IEEE80211_HW_BEACON_FILTER | | 1296 | IEEE80211_HW_BEACON_FILTER | |
1237 | IEEE80211_HW_SUPPORTS_UAPSD; | 1297 | IEEE80211_HW_SUPPORTS_UAPSD; |
@@ -1242,6 +1302,9 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1242 | 1302 | ||
1243 | wl->hw->queues = 4; | 1303 | wl->hw->queues = 4; |
1244 | 1304 | ||
1305 | if (wl->use_eeprom) | ||
1306 | wl1251_read_eeprom_mac(wl); | ||
1307 | |||
1245 | ret = wl1251_register_hw(wl); | 1308 | ret = wl1251_register_hw(wl); |
1246 | if (ret) | 1309 | if (ret) |
1247 | goto out; | 1310 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 851dfb65e474..b55cb2bd459a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work) | |||
45 | goto out; | 45 | goto out; |
46 | 46 | ||
47 | wl1251_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1251_debug(DEBUG_PSM, "chip to elp"); |
48 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 48 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
49 | wl->elp = true; | 49 | wl->elp = true; |
50 | 50 | ||
51 | out: | 51 | out: |
@@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
79 | start = jiffies; | 79 | start = jiffies; |
80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); |
81 | 81 | ||
82 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 82 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
83 | 83 | ||
84 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 84 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * FIXME: we should wait for irq from chip but, as a temporary | 87 | * FIXME: we should wait for irq from chip but, as a temporary |
@@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
93 | return -ETIMEDOUT; | 93 | return -ETIMEDOUT; |
94 | } | 94 | } |
95 | msleep(1); | 95 | msleep(1); |
96 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 96 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
97 | } | 97 | } |
98 | 98 | ||
99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | 99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", |
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index 0ca3b4326056..d16edd9bf06c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h | |||
@@ -46,7 +46,14 @@ | |||
46 | #define SOR_CFG (REGISTERS_BASE + 0x0800) | 46 | #define SOR_CFG (REGISTERS_BASE + 0x0800) |
47 | #define ECPU_CTRL (REGISTERS_BASE + 0x0804) | 47 | #define ECPU_CTRL (REGISTERS_BASE + 0x0804) |
48 | #define HI_CFG (REGISTERS_BASE + 0x0808) | 48 | #define HI_CFG (REGISTERS_BASE + 0x0808) |
49 | |||
50 | /* EEPROM registers */ | ||
49 | #define EE_START (REGISTERS_BASE + 0x080C) | 51 | #define EE_START (REGISTERS_BASE + 0x080C) |
52 | #define EE_CTL (REGISTERS_BASE + 0x2000) | ||
53 | #define EE_DATA (REGISTERS_BASE + 0x2004) | ||
54 | #define EE_ADDR (REGISTERS_BASE + 0x2008) | ||
55 | |||
56 | #define EE_CTL_READ 2 | ||
50 | 57 | ||
51 | #define CHIP_ID_B (REGISTERS_BASE + 0x5674) | 58 | #define CHIP_ID_B (REGISTERS_BASE + 0x5674) |
52 | 59 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 6f229e0990f4..851515836a7f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -74,12 +74,6 @@ static void wl1251_rx_status(struct wl1251 *wl, | |||
74 | 74 | ||
75 | status->signal = desc->rssi; | 75 | status->signal = desc->rssi; |
76 | 76 | ||
77 | /* | ||
78 | * FIXME: guessing that snr needs to be divided by two, otherwise | ||
79 | * the values don't make any sense | ||
80 | */ | ||
81 | status->noise = desc->rssi - desc->snr / 2; | ||
82 | |||
83 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 77 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
84 | 78 | ||
85 | status->flag |= RX_FLAG_TSFT; | 79 | status->flag |= RX_FLAG_TSFT; |
@@ -189,6 +183,4 @@ void wl1251_rx(struct wl1251 *wl) | |||
189 | 183 | ||
190 | /* Finally, we need to ACK the RX */ | 184 | /* Finally, we need to ACK the RX */ |
191 | wl1251_rx_ack(wl); | 185 | wl1251_rx_ack(wl); |
192 | |||
193 | return; | ||
194 | } | 186 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 9423f22bdced..d234285c2c81 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -20,20 +20,14 @@ | |||
20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) | 20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) |
21 | */ | 21 | */ |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/crc7.h> | ||
24 | #include <linux/mod_devicetable.h> | 23 | #include <linux/mod_devicetable.h> |
25 | #include <linux/irq.h> | ||
26 | #include <linux/mmc/sdio_func.h> | 24 | #include <linux/mmc/sdio_func.h> |
27 | #include <linux/mmc/sdio_ids.h> | 25 | #include <linux/mmc/sdio_ids.h> |
28 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/spi/wl12xx.h> | ||
28 | #include <linux/irq.h> | ||
29 | 29 | ||
30 | #include "wl1251.h" | 30 | #include "wl1251.h" |
31 | #include "wl12xx_80211.h" | ||
32 | #include "wl1251_reg.h" | ||
33 | #include "wl1251_ps.h" | ||
34 | #include "wl1251_io.h" | ||
35 | #include "wl1251_tx.h" | ||
36 | #include "wl1251_debugfs.h" | ||
37 | 31 | ||
38 | #ifndef SDIO_VENDOR_ID_TI | 32 | #ifndef SDIO_VENDOR_ID_TI |
39 | #define SDIO_VENDOR_ID_TI 0x104c | 33 | #define SDIO_VENDOR_ID_TI 0x104c |
@@ -43,6 +37,8 @@ | |||
43 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 | 37 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 |
44 | #endif | 38 | #endif |
45 | 39 | ||
40 | static struct wl12xx_platform_data *wl12xx_board_data; | ||
41 | |||
46 | static struct sdio_func *wl_to_func(struct wl1251 *wl) | 42 | static struct sdio_func *wl_to_func(struct wl1251 *wl) |
47 | { | 43 | { |
48 | return wl->if_priv; | 44 | return wl->if_priv; |
@@ -65,7 +61,8 @@ static const struct sdio_device_id wl1251_devices[] = { | |||
65 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); | 61 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); |
66 | 62 | ||
67 | 63 | ||
68 | void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | 64 | static void wl1251_sdio_read(struct wl1251 *wl, int addr, |
65 | void *buf, size_t len) | ||
69 | { | 66 | { |
70 | int ret; | 67 | int ret; |
71 | struct sdio_func *func = wl_to_func(wl); | 68 | struct sdio_func *func = wl_to_func(wl); |
@@ -77,7 +74,8 @@ void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
77 | sdio_release_host(func); | 74 | sdio_release_host(func); |
78 | } | 75 | } |
79 | 76 | ||
80 | void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | 77 | static void wl1251_sdio_write(struct wl1251 *wl, int addr, |
78 | void *buf, size_t len) | ||
81 | { | 79 | { |
82 | int ret; | 80 | int ret; |
83 | struct sdio_func *func = wl_to_func(wl); | 81 | struct sdio_func *func = wl_to_func(wl); |
@@ -89,7 +87,33 @@ void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
89 | sdio_release_host(func); | 87 | sdio_release_host(func); |
90 | } | 88 | } |
91 | 89 | ||
92 | void wl1251_sdio_reset(struct wl1251 *wl) | 90 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) |
91 | { | ||
92 | int ret = 0; | ||
93 | struct sdio_func *func = wl_to_func(wl); | ||
94 | |||
95 | sdio_claim_host(func); | ||
96 | *val = sdio_readb(func, addr, &ret); | ||
97 | sdio_release_host(func); | ||
98 | |||
99 | if (ret) | ||
100 | wl1251_error("sdio_readb failed (%d)", ret); | ||
101 | } | ||
102 | |||
103 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
104 | { | ||
105 | int ret = 0; | ||
106 | struct sdio_func *func = wl_to_func(wl); | ||
107 | |||
108 | sdio_claim_host(func); | ||
109 | sdio_writeb(func, val, addr, &ret); | ||
110 | sdio_release_host(func); | ||
111 | |||
112 | if (ret) | ||
113 | wl1251_error("sdio_writeb failed (%d)", ret); | ||
114 | } | ||
115 | |||
116 | static void wl1251_sdio_reset(struct wl1251 *wl) | ||
93 | { | 117 | { |
94 | } | 118 | } |
95 | 119 | ||
@@ -111,19 +135,64 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) | |||
111 | sdio_release_host(func); | 135 | sdio_release_host(func); |
112 | } | 136 | } |
113 | 137 | ||
114 | void wl1251_sdio_set_power(bool enable) | 138 | /* Interrupts when using dedicated WLAN_IRQ pin */ |
139 | static irqreturn_t wl1251_line_irq(int irq, void *cookie) | ||
140 | { | ||
141 | struct wl1251 *wl = cookie; | ||
142 | |||
143 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
144 | |||
145 | return IRQ_HANDLED; | ||
146 | } | ||
147 | |||
148 | static void wl1251_enable_line_irq(struct wl1251 *wl) | ||
115 | { | 149 | { |
150 | return enable_irq(wl->irq); | ||
116 | } | 151 | } |
117 | 152 | ||
118 | struct wl1251_if_operations wl1251_sdio_ops = { | 153 | static void wl1251_disable_line_irq(struct wl1251 *wl) |
154 | { | ||
155 | return disable_irq(wl->irq); | ||
156 | } | ||
157 | |||
158 | static void wl1251_sdio_set_power(bool enable) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | static struct wl1251_if_operations wl1251_sdio_ops = { | ||
119 | .read = wl1251_sdio_read, | 163 | .read = wl1251_sdio_read, |
120 | .write = wl1251_sdio_write, | 164 | .write = wl1251_sdio_write, |
165 | .write_elp = wl1251_sdio_write_elp, | ||
166 | .read_elp = wl1251_sdio_read_elp, | ||
121 | .reset = wl1251_sdio_reset, | 167 | .reset = wl1251_sdio_reset, |
122 | .enable_irq = wl1251_sdio_enable_irq, | ||
123 | .disable_irq = wl1251_sdio_disable_irq, | ||
124 | }; | 168 | }; |
125 | 169 | ||
126 | int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | 170 | static int wl1251_platform_probe(struct platform_device *pdev) |
171 | { | ||
172 | if (pdev->id != -1) { | ||
173 | wl1251_error("can only handle single device"); | ||
174 | return -ENODEV; | ||
175 | } | ||
176 | |||
177 | wl12xx_board_data = pdev->dev.platform_data; | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Dummy platform_driver for passing platform_data to this driver, | ||
183 | * until we have a way to pass this through SDIO subsystem or | ||
184 | * some other way. | ||
185 | */ | ||
186 | static struct platform_driver wl1251_platform_driver = { | ||
187 | .driver = { | ||
188 | .name = "wl1251_data", | ||
189 | .owner = THIS_MODULE, | ||
190 | }, | ||
191 | .probe = wl1251_platform_probe, | ||
192 | }; | ||
193 | |||
194 | static int wl1251_sdio_probe(struct sdio_func *func, | ||
195 | const struct sdio_device_id *id) | ||
127 | { | 196 | { |
128 | int ret; | 197 | int ret; |
129 | struct wl1251 *wl; | 198 | struct wl1251 *wl; |
@@ -141,20 +210,50 @@ int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
141 | goto release; | 210 | goto release; |
142 | 211 | ||
143 | sdio_set_block_size(func, 512); | 212 | sdio_set_block_size(func, 512); |
213 | sdio_release_host(func); | ||
144 | 214 | ||
145 | SET_IEEE80211_DEV(hw, &func->dev); | 215 | SET_IEEE80211_DEV(hw, &func->dev); |
146 | wl->if_priv = func; | 216 | wl->if_priv = func; |
147 | wl->if_ops = &wl1251_sdio_ops; | 217 | wl->if_ops = &wl1251_sdio_ops; |
148 | wl->set_power = wl1251_sdio_set_power; | 218 | wl->set_power = wl1251_sdio_set_power; |
149 | 219 | ||
150 | sdio_release_host(func); | 220 | if (wl12xx_board_data != NULL) { |
221 | wl->set_power = wl12xx_board_data->set_power; | ||
222 | wl->irq = wl12xx_board_data->irq; | ||
223 | wl->use_eeprom = wl12xx_board_data->use_eeprom; | ||
224 | } | ||
225 | |||
226 | if (wl->irq) { | ||
227 | ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); | ||
228 | if (ret < 0) { | ||
229 | wl1251_error("request_irq() failed: %d", ret); | ||
230 | goto disable; | ||
231 | } | ||
232 | |||
233 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
234 | disable_irq(wl->irq); | ||
235 | |||
236 | wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; | ||
237 | wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; | ||
238 | |||
239 | wl1251_info("using dedicated interrupt line"); | ||
240 | } else { | ||
241 | wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; | ||
242 | wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; | ||
243 | |||
244 | wl1251_info("using SDIO interrupt"); | ||
245 | } | ||
246 | |||
151 | ret = wl1251_init_ieee80211(wl); | 247 | ret = wl1251_init_ieee80211(wl); |
152 | if (ret) | 248 | if (ret) |
153 | goto disable; | 249 | goto out_free_irq; |
154 | 250 | ||
155 | sdio_set_drvdata(func, wl); | 251 | sdio_set_drvdata(func, wl); |
156 | return ret; | 252 | return ret; |
157 | 253 | ||
254 | out_free_irq: | ||
255 | if (wl->irq) | ||
256 | free_irq(wl->irq, wl); | ||
158 | disable: | 257 | disable: |
159 | sdio_claim_host(func); | 258 | sdio_claim_host(func); |
160 | sdio_disable_func(func); | 259 | sdio_disable_func(func); |
@@ -167,6 +266,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) | |||
167 | { | 266 | { |
168 | struct wl1251 *wl = sdio_get_drvdata(func); | 267 | struct wl1251 *wl = sdio_get_drvdata(func); |
169 | 268 | ||
269 | if (wl->irq) | ||
270 | free_irq(wl->irq, wl); | ||
170 | wl1251_free_hw(wl); | 271 | wl1251_free_hw(wl); |
171 | 272 | ||
172 | sdio_claim_host(func); | 273 | sdio_claim_host(func); |
@@ -186,6 +287,12 @@ static int __init wl1251_sdio_init(void) | |||
186 | { | 287 | { |
187 | int err; | 288 | int err; |
188 | 289 | ||
290 | err = platform_driver_register(&wl1251_platform_driver); | ||
291 | if (err) { | ||
292 | wl1251_error("failed to register platform driver: %d", err); | ||
293 | return err; | ||
294 | } | ||
295 | |||
189 | err = sdio_register_driver(&wl1251_sdio_driver); | 296 | err = sdio_register_driver(&wl1251_sdio_driver); |
190 | if (err) | 297 | if (err) |
191 | wl1251_error("failed to register sdio driver: %d", err); | 298 | wl1251_error("failed to register sdio driver: %d", err); |
@@ -195,6 +302,7 @@ static int __init wl1251_sdio_init(void) | |||
195 | static void __exit wl1251_sdio_exit(void) | 302 | static void __exit wl1251_sdio_exit(void) |
196 | { | 303 | { |
197 | sdio_unregister_driver(&wl1251_sdio_driver); | 304 | sdio_unregister_driver(&wl1251_sdio_driver); |
305 | platform_driver_unregister(&wl1251_platform_driver); | ||
198 | wl1251_notice("unloaded"); | 306 | wl1251_notice("unloaded"); |
199 | } | 307 | } |
200 | 308 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 3bfb59bd4635..e81474203a23 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -310,7 +310,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) | |||
310 | 310 | ||
311 | static struct spi_driver wl1251_spi_driver = { | 311 | static struct spi_driver wl1251_spi_driver = { |
312 | .driver = { | 312 | .driver = { |
313 | .name = "wl1251", | 313 | .name = DRIVER_NAME, |
314 | .bus = &spi_bus_type, | 314 | .bus = &spi_bus_type, |
315 | .owner = THIS_MODULE, | 315 | .owner = THIS_MODULE, |
316 | }, | 316 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 97ea5096bc8c..6f1b6b5640c0 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -53,6 +53,9 @@ enum { | |||
53 | DEBUG_MAC80211 = BIT(11), | 53 | DEBUG_MAC80211 = BIT(11), |
54 | DEBUG_CMD = BIT(12), | 54 | DEBUG_CMD = BIT(12), |
55 | DEBUG_ACX = BIT(13), | 55 | DEBUG_ACX = BIT(13), |
56 | DEBUG_SDIO = BIT(14), | ||
57 | DEBUG_FILTERS = BIT(15), | ||
58 | DEBUG_ADHOC = BIT(16), | ||
56 | DEBUG_ALL = ~0, | 59 | DEBUG_ALL = ~0, |
57 | }; | 60 | }; |
58 | 61 | ||
@@ -110,6 +113,9 @@ enum { | |||
110 | #define WL1271_FW_NAME "wl1271-fw.bin" | 113 | #define WL1271_FW_NAME "wl1271-fw.bin" |
111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 114 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | 115 | ||
116 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | ||
117 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | ||
118 | |||
113 | /* NVS data structure */ | 119 | /* NVS data structure */ |
114 | #define WL1271_NVS_SECTION_SIZE 468 | 120 | #define WL1271_NVS_SECTION_SIZE 468 |
115 | 121 | ||
@@ -142,14 +148,7 @@ struct wl1271_nvs_file { | |||
142 | */ | 148 | */ |
143 | #undef WL1271_80211A_ENABLED | 149 | #undef WL1271_80211A_ENABLED |
144 | 150 | ||
145 | /* | 151 | #define WL1271_BUSY_WORD_CNT 1 |
146 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
147 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
148 | * with this mode occasionally on boot, so lets have three for now. A value of | ||
149 | * three should make sure, that the chipset will always be ready, though this | ||
150 | * will impact throughput and latencies slightly. | ||
151 | */ | ||
152 | #define WL1271_BUSY_WORD_CNT 3 | ||
153 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 152 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
154 | 153 | ||
155 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 154 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
@@ -334,11 +333,27 @@ struct wl1271_scan { | |||
334 | u8 probe_requests; | 333 | u8 probe_requests; |
335 | }; | 334 | }; |
336 | 335 | ||
336 | struct wl1271_if_operations { | ||
337 | void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
338 | bool fixed); | ||
339 | void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
340 | bool fixed); | ||
341 | void (*reset)(struct wl1271 *wl); | ||
342 | void (*init)(struct wl1271 *wl); | ||
343 | void (*power)(struct wl1271 *wl, bool enable); | ||
344 | struct device* (*dev)(struct wl1271 *wl); | ||
345 | void (*enable_irq)(struct wl1271 *wl); | ||
346 | void (*disable_irq)(struct wl1271 *wl); | ||
347 | }; | ||
348 | |||
337 | struct wl1271 { | 349 | struct wl1271 { |
350 | struct platform_device *plat_dev; | ||
338 | struct ieee80211_hw *hw; | 351 | struct ieee80211_hw *hw; |
339 | bool mac80211_registered; | 352 | bool mac80211_registered; |
340 | 353 | ||
341 | struct spi_device *spi; | 354 | void *if_priv; |
355 | |||
356 | struct wl1271_if_operations *if_ops; | ||
342 | 357 | ||
343 | void (*set_power)(bool enable); | 358 | void (*set_power)(bool enable); |
344 | int irq; | 359 | int irq; |
@@ -357,6 +372,9 @@ struct wl1271 { | |||
357 | #define WL1271_FLAG_IN_ELP (6) | 372 | #define WL1271_FLAG_IN_ELP (6) |
358 | #define WL1271_FLAG_PSM (7) | 373 | #define WL1271_FLAG_PSM (7) |
359 | #define WL1271_FLAG_PSM_REQUESTED (8) | 374 | #define WL1271_FLAG_PSM_REQUESTED (8) |
375 | #define WL1271_FLAG_IRQ_PENDING (9) | ||
376 | #define WL1271_FLAG_IRQ_RUNNING (10) | ||
377 | #define WL1271_FLAG_IDLE (11) | ||
360 | unsigned long flags; | 378 | unsigned long flags; |
361 | 379 | ||
362 | struct wl1271_partition_set part; | 380 | struct wl1271_partition_set part; |
@@ -370,9 +388,12 @@ struct wl1271 { | |||
370 | size_t fw_len; | 388 | size_t fw_len; |
371 | struct wl1271_nvs_file *nvs; | 389 | struct wl1271_nvs_file *nvs; |
372 | 390 | ||
391 | s8 hw_pg_ver; | ||
392 | |||
373 | u8 bssid[ETH_ALEN]; | 393 | u8 bssid[ETH_ALEN]; |
374 | u8 mac_addr[ETH_ALEN]; | 394 | u8 mac_addr[ETH_ALEN]; |
375 | u8 bss_type; | 395 | u8 bss_type; |
396 | u8 set_bss_type; | ||
376 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | 397 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; |
377 | u8 ssid_len; | 398 | u8 ssid_len; |
378 | int channel; | 399 | int channel; |
@@ -382,13 +403,13 @@ struct wl1271 { | |||
382 | /* Accounting for allocated / available TX blocks on HW */ | 403 | /* Accounting for allocated / available TX blocks on HW */ |
383 | u32 tx_blocks_freed[NUM_TX_QUEUES]; | 404 | u32 tx_blocks_freed[NUM_TX_QUEUES]; |
384 | u32 tx_blocks_available; | 405 | u32 tx_blocks_available; |
385 | u8 tx_results_count; | 406 | u32 tx_results_count; |
386 | 407 | ||
387 | /* Transmitted TX packets counter for chipset interface */ | 408 | /* Transmitted TX packets counter for chipset interface */ |
388 | int tx_packets_count; | 409 | u32 tx_packets_count; |
389 | 410 | ||
390 | /* Time-offset between host and chipset clocks */ | 411 | /* Time-offset between host and chipset clocks */ |
391 | int time_offset; | 412 | s64 time_offset; |
392 | 413 | ||
393 | /* Session counter for the chipset */ | 414 | /* Session counter for the chipset */ |
394 | int session_counter; | 415 | int session_counter; |
@@ -403,8 +424,7 @@ struct wl1271 { | |||
403 | 424 | ||
404 | /* Security sequence number counters */ | 425 | /* Security sequence number counters */ |
405 | u8 tx_security_last_seq; | 426 | u8 tx_security_last_seq; |
406 | u16 tx_security_seq_16; | 427 | s64 tx_security_seq; |
407 | u32 tx_security_seq_32; | ||
408 | 428 | ||
409 | /* FW Rx counter */ | 429 | /* FW Rx counter */ |
410 | u32 rx_counter; | 430 | u32 rx_counter; |
@@ -430,14 +450,19 @@ struct wl1271 { | |||
430 | /* currently configured rate set */ | 450 | /* currently configured rate set */ |
431 | u32 sta_rate_set; | 451 | u32 sta_rate_set; |
432 | u32 basic_rate_set; | 452 | u32 basic_rate_set; |
453 | u32 basic_rate; | ||
433 | u32 rate_set; | 454 | u32 rate_set; |
434 | 455 | ||
435 | /* The current band */ | 456 | /* The current band */ |
436 | enum ieee80211_band band; | 457 | enum ieee80211_band band; |
437 | 458 | ||
459 | /* Beaconing interval (needed for ad-hoc) */ | ||
460 | u32 beacon_int; | ||
461 | |||
438 | /* Default key (for WEP) */ | 462 | /* Default key (for WEP) */ |
439 | u32 default_key; | 463 | u32 default_key; |
440 | 464 | ||
465 | unsigned int filters; | ||
441 | unsigned int rx_config; | 466 | unsigned int rx_config; |
442 | unsigned int rx_filter; | 467 | unsigned int rx_filter; |
443 | 468 | ||
@@ -450,10 +475,13 @@ struct wl1271 { | |||
450 | /* in dBm */ | 475 | /* in dBm */ |
451 | int power_level; | 476 | int power_level; |
452 | 477 | ||
478 | int rssi_thold; | ||
479 | int last_rssi_event; | ||
480 | |||
453 | struct wl1271_stats stats; | 481 | struct wl1271_stats stats; |
454 | struct wl1271_debugfs debugfs; | 482 | struct wl1271_debugfs debugfs; |
455 | 483 | ||
456 | u32 buffer_32; | 484 | __le32 buffer_32; |
457 | u32 buffer_cmd; | 485 | u32 buffer_cmd; |
458 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; | 486 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; |
459 | 487 | ||
@@ -465,6 +493,8 @@ struct wl1271 { | |||
465 | /* Current chipset configuration */ | 493 | /* Current chipset configuration */ |
466 | struct conf_drv_settings conf; | 494 | struct conf_drv_settings conf; |
467 | 495 | ||
496 | bool sg_enabled; | ||
497 | |||
468 | struct list_head list; | 498 | struct list_head list; |
469 | }; | 499 | }; |
470 | 500 | ||
@@ -477,7 +507,8 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
477 | 507 | ||
478 | #define WL1271_DEFAULT_POWER_LEVEL 0 | 508 | #define WL1271_DEFAULT_POWER_LEVEL 0 |
479 | 509 | ||
480 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 510 | #define WL1271_TX_QUEUE_LOW_WATERMARK 10 |
511 | #define WL1271_TX_QUEUE_HIGH_WATERMARK 25 | ||
481 | 512 | ||
482 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power | 513 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
483 | on in case is has been shut down shortly before */ | 514 | on in case is has been shut down shortly before */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 308782421fce..e19e2f8f1e52 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "wl1271.h" | 32 | #include "wl1271.h" |
33 | #include "wl12xx_80211.h" | 33 | #include "wl12xx_80211.h" |
34 | #include "wl1271_reg.h" | 34 | #include "wl1271_reg.h" |
35 | #include "wl1271_spi.h" | ||
36 | #include "wl1271_ps.h" | 35 | #include "wl1271_ps.h" |
37 | 36 | ||
38 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) | 37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) |
@@ -137,12 +136,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
137 | goto out; | 136 | goto out; |
138 | } | 137 | } |
139 | 138 | ||
140 | /* | 139 | acx->current_tx_power = power * 10; |
141 | * FIXME: This is a workaround needed while we don't the correct | ||
142 | * calibration, to avoid distortions | ||
143 | */ | ||
144 | /* acx->current_tx_power = power * 10; */ | ||
145 | acx->current_tx_power = 120; | ||
146 | 140 | ||
147 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | 141 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
148 | if (ret < 0) { | 142 | if (ret < 0) { |
@@ -511,12 +505,17 @@ out: | |||
511 | return ret; | 505 | return ret; |
512 | } | 506 | } |
513 | 507 | ||
514 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | 508 | #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff |
509 | |||
510 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) | ||
515 | { | 511 | { |
516 | struct acx_conn_monit_params *acx; | 512 | struct acx_conn_monit_params *acx; |
513 | u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; | ||
514 | u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE; | ||
517 | int ret; | 515 | int ret; |
518 | 516 | ||
519 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | 517 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s", |
518 | enable ? "enabled" : "disabled"); | ||
520 | 519 | ||
521 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 520 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
522 | if (!acx) { | 521 | if (!acx) { |
@@ -524,8 +523,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl) | |||
524 | goto out; | 523 | goto out; |
525 | } | 524 | } |
526 | 525 | ||
527 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | 526 | if (enable) { |
528 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | 527 | threshold = wl->conf.conn.synch_fail_thold; |
528 | timeout = wl->conf.conn.bss_lose_timeout; | ||
529 | } | ||
530 | |||
531 | acx->synch_fail_thold = cpu_to_le32(threshold); | ||
532 | acx->bss_lose_timeout = cpu_to_le32(timeout); | ||
529 | 533 | ||
530 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | 534 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, |
531 | acx, sizeof(*acx)); | 535 | acx, sizeof(*acx)); |
@@ -541,7 +545,7 @@ out: | |||
541 | } | 545 | } |
542 | 546 | ||
543 | 547 | ||
544 | int wl1271_acx_sg_enable(struct wl1271 *wl) | 548 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable) |
545 | { | 549 | { |
546 | struct acx_bt_wlan_coex *pta; | 550 | struct acx_bt_wlan_coex *pta; |
547 | int ret; | 551 | int ret; |
@@ -554,7 +558,10 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) | |||
554 | goto out; | 558 | goto out; |
555 | } | 559 | } |
556 | 560 | ||
557 | pta->enable = SG_ENABLE; | 561 | if (enable) |
562 | pta->enable = wl->conf.sg.state; | ||
563 | else | ||
564 | pta->enable = CONF_SG_DISABLE; | ||
558 | 565 | ||
559 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); | 566 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); |
560 | if (ret < 0) { | 567 | if (ret < 0) { |
@@ -571,7 +578,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
571 | { | 578 | { |
572 | struct acx_bt_wlan_coex_param *param; | 579 | struct acx_bt_wlan_coex_param *param; |
573 | struct conf_sg_settings *c = &wl->conf.sg; | 580 | struct conf_sg_settings *c = &wl->conf.sg; |
574 | int ret; | 581 | int i, ret; |
575 | 582 | ||
576 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 583 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); |
577 | 584 | ||
@@ -582,19 +589,9 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
582 | } | 589 | } |
583 | 590 | ||
584 | /* BT-WLAN coext parameters */ | 591 | /* BT-WLAN coext parameters */ |
585 | param->per_threshold = cpu_to_le32(c->per_threshold); | 592 | for (i = 0; i < CONF_SG_PARAMS_MAX; i++) |
586 | param->max_scan_compensation_time = | 593 | param->params[i] = cpu_to_le32(c->params[i]); |
587 | cpu_to_le32(c->max_scan_compensation_time); | 594 | param->param_idx = CONF_SG_PARAMS_ALL; |
588 | param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); | ||
589 | param->load_ratio = c->load_ratio; | ||
590 | param->auto_ps_mode = c->auto_ps_mode; | ||
591 | param->probe_req_compensation = c->probe_req_compensation; | ||
592 | param->scan_window_compensation = c->scan_window_compensation; | ||
593 | param->antenna_config = c->antenna_config; | ||
594 | param->beacon_miss_threshold = c->beacon_miss_threshold; | ||
595 | param->rate_adaptation_threshold = | ||
596 | cpu_to_le32(c->rate_adaptation_threshold); | ||
597 | param->rate_adaptation_snr = c->rate_adaptation_snr; | ||
598 | 595 | ||
599 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 596 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
600 | if (ret < 0) { | 597 | if (ret < 0) { |
@@ -806,7 +803,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
806 | 803 | ||
807 | /* configure one basic rate class */ | 804 | /* configure one basic rate class */ |
808 | idx = ACX_TX_BASIC_RATE; | 805 | idx = ACX_TX_BASIC_RATE; |
809 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); | 806 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); |
810 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | 807 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
811 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | 808 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
812 | acx->rate_class[idx].aflags = c->aflags; | 809 | acx->rate_class[idx].aflags = c->aflags; |
@@ -1143,3 +1140,129 @@ out: | |||
1143 | kfree(acx); | 1140 | kfree(acx); |
1144 | return ret; | 1141 | return ret; |
1145 | } | 1142 | } |
1143 | |||
1144 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) | ||
1145 | { | ||
1146 | struct wl1271_acx_keep_alive_mode *acx = NULL; | ||
1147 | int ret = 0; | ||
1148 | |||
1149 | wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); | ||
1150 | |||
1151 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1152 | if (!acx) { | ||
1153 | ret = -ENOMEM; | ||
1154 | goto out; | ||
1155 | } | ||
1156 | |||
1157 | acx->enabled = enable; | ||
1158 | |||
1159 | ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); | ||
1160 | if (ret < 0) { | ||
1161 | wl1271_warning("acx keep alive mode failed: %d", ret); | ||
1162 | goto out; | ||
1163 | } | ||
1164 | |||
1165 | out: | ||
1166 | kfree(acx); | ||
1167 | return ret; | ||
1168 | } | ||
1169 | |||
1170 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) | ||
1171 | { | ||
1172 | struct wl1271_acx_keep_alive_config *acx = NULL; | ||
1173 | int ret = 0; | ||
1174 | |||
1175 | wl1271_debug(DEBUG_ACX, "acx keep alive config"); | ||
1176 | |||
1177 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1178 | if (!acx) { | ||
1179 | ret = -ENOMEM; | ||
1180 | goto out; | ||
1181 | } | ||
1182 | |||
1183 | acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); | ||
1184 | acx->index = index; | ||
1185 | acx->tpl_validation = tpl_valid; | ||
1186 | acx->trigger = ACX_KEEP_ALIVE_NO_TX; | ||
1187 | |||
1188 | ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, | ||
1189 | acx, sizeof(*acx)); | ||
1190 | if (ret < 0) { | ||
1191 | wl1271_warning("acx keep alive config failed: %d", ret); | ||
1192 | goto out; | ||
1193 | } | ||
1194 | |||
1195 | out: | ||
1196 | kfree(acx); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1201 | s16 thold, u8 hyst) | ||
1202 | { | ||
1203 | struct wl1271_acx_rssi_snr_trigger *acx = NULL; | ||
1204 | int ret = 0; | ||
1205 | |||
1206 | wl1271_debug(DEBUG_ACX, "acx rssi snr trigger"); | ||
1207 | |||
1208 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1209 | if (!acx) { | ||
1210 | ret = -ENOMEM; | ||
1211 | goto out; | ||
1212 | } | ||
1213 | |||
1214 | wl->last_rssi_event = -1; | ||
1215 | |||
1216 | acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); | ||
1217 | acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; | ||
1218 | acx->type = WL1271_ACX_TRIG_TYPE_EDGE; | ||
1219 | if (enable) | ||
1220 | acx->enable = WL1271_ACX_TRIG_ENABLE; | ||
1221 | else | ||
1222 | acx->enable = WL1271_ACX_TRIG_DISABLE; | ||
1223 | |||
1224 | acx->index = WL1271_ACX_TRIG_IDX_RSSI; | ||
1225 | acx->dir = WL1271_ACX_TRIG_DIR_BIDIR; | ||
1226 | acx->threshold = cpu_to_le16(thold); | ||
1227 | acx->hysteresis = hyst; | ||
1228 | |||
1229 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx)); | ||
1230 | if (ret < 0) { | ||
1231 | wl1271_warning("acx rssi snr trigger setting failed: %d", ret); | ||
1232 | goto out; | ||
1233 | } | ||
1234 | |||
1235 | out: | ||
1236 | kfree(acx); | ||
1237 | return ret; | ||
1238 | } | ||
1239 | |||
1240 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) | ||
1241 | { | ||
1242 | struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; | ||
1243 | struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; | ||
1244 | int ret = 0; | ||
1245 | |||
1246 | wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights"); | ||
1247 | |||
1248 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1249 | if (!acx) { | ||
1250 | ret = -ENOMEM; | ||
1251 | goto out; | ||
1252 | } | ||
1253 | |||
1254 | acx->rssi_beacon = c->avg_weight_rssi_beacon; | ||
1255 | acx->rssi_data = c->avg_weight_rssi_data; | ||
1256 | acx->snr_beacon = c->avg_weight_snr_beacon; | ||
1257 | acx->snr_data = c->avg_weight_snr_data; | ||
1258 | |||
1259 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx)); | ||
1260 | if (ret < 0) { | ||
1261 | wl1271_warning("acx rssi snr trigger weights failed: %d", ret); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | |||
1265 | out: | ||
1266 | kfree(acx); | ||
1267 | return ret; | ||
1268 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index aeccc98581eb..420e7e2fc021 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -392,81 +392,27 @@ struct acx_conn_monit_params { | |||
392 | __le32 bss_lose_timeout; /* number of TU's from synch fail */ | 392 | __le32 bss_lose_timeout; /* number of TU's from synch fail */ |
393 | } __attribute__ ((packed)); | 393 | } __attribute__ ((packed)); |
394 | 394 | ||
395 | enum { | ||
396 | SG_ENABLE = 0, | ||
397 | SG_DISABLE, | ||
398 | SG_SENSE_NO_ACTIVITY, | ||
399 | SG_SENSE_ACTIVE | ||
400 | }; | ||
401 | |||
402 | struct acx_bt_wlan_coex { | 395 | struct acx_bt_wlan_coex { |
403 | struct acx_header header; | 396 | struct acx_header header; |
404 | 397 | ||
405 | /* | ||
406 | * 0 -> PTA enabled | ||
407 | * 1 -> PTA disabled | ||
408 | * 2 -> sense no active mode, i.e. | ||
409 | * an interrupt is sent upon | ||
410 | * BT activity. | ||
411 | * 3 -> PTA is switched on in response | ||
412 | * to the interrupt sending. | ||
413 | */ | ||
414 | u8 enable; | 398 | u8 enable; |
415 | u8 pad[3]; | 399 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 400 | } __attribute__ ((packed)); |
417 | 401 | ||
418 | struct acx_dco_itrim_params { | 402 | struct acx_bt_wlan_coex_param { |
419 | struct acx_header header; | 403 | struct acx_header header; |
420 | 404 | ||
421 | u8 enable; | 405 | __le32 params[CONF_SG_PARAMS_MAX]; |
406 | u8 param_idx; | ||
422 | u8 padding[3]; | 407 | u8 padding[3]; |
423 | __le32 timeout; | ||
424 | } __attribute__ ((packed)); | 408 | } __attribute__ ((packed)); |
425 | 409 | ||
426 | #define PTA_ANTENNA_TYPE_DEF (0) | 410 | struct acx_dco_itrim_params { |
427 | #define PTA_BT_HP_MAXTIME_DEF (2000) | ||
428 | #define PTA_WLAN_HP_MAX_TIME_DEF (5000) | ||
429 | #define PTA_SENSE_DISABLE_TIMER_DEF (1350) | ||
430 | #define PTA_PROTECTIVE_RX_TIME_DEF (1500) | ||
431 | #define PTA_PROTECTIVE_TX_TIME_DEF (1500) | ||
432 | #define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) | ||
433 | #define PTA_SIGNALING_TYPE_DEF (1) | ||
434 | #define PTA_AFH_LEVERAGE_ON_DEF (0) | ||
435 | #define PTA_NUMBER_QUIET_CYCLE_DEF (0) | ||
436 | #define PTA_MAX_NUM_CTS_DEF (3) | ||
437 | #define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) | ||
438 | #define PTA_NUMBER_OF_BT_PACKETS_DEF (2) | ||
439 | #define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) | ||
440 | #define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) | ||
441 | #define PTA_CYCLE_TIME_FAST_DEF (8700) | ||
442 | #define PTA_RX_FOR_AVALANCHE_DEF (5) | ||
443 | #define PTA_ELP_HP_DEF (0) | ||
444 | #define PTA_ANTI_STARVE_PERIOD_DEF (500) | ||
445 | #define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) | ||
446 | #define PTA_ALLOW_PA_SD_DEF (1) | ||
447 | #define PTA_TIME_BEFORE_BEACON_DEF (6300) | ||
448 | #define PTA_HPDM_MAX_TIME_DEF (1600) | ||
449 | #define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) | ||
450 | #define PTA_AUTO_MODE_NO_CTS_DEF (0) | ||
451 | #define PTA_BT_HP_RESPECTED_DEF (3) | ||
452 | #define PTA_WLAN_RX_MIN_RATE_DEF (24) | ||
453 | #define PTA_ACK_MODE_DEF (1) | ||
454 | |||
455 | struct acx_bt_wlan_coex_param { | ||
456 | struct acx_header header; | 411 | struct acx_header header; |
457 | 412 | ||
458 | __le32 per_threshold; | 413 | u8 enable; |
459 | __le32 max_scan_compensation_time; | ||
460 | __le16 nfs_sample_interval; | ||
461 | u8 load_ratio; | ||
462 | u8 auto_ps_mode; | ||
463 | u8 probe_req_compensation; | ||
464 | u8 scan_window_compensation; | ||
465 | u8 antenna_config; | ||
466 | u8 beacon_miss_threshold; | ||
467 | __le32 rate_adaptation_threshold; | ||
468 | s8 rate_adaptation_snr; | ||
469 | u8 padding[3]; | 414 | u8 padding[3]; |
415 | __le32 timeout; | ||
470 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
471 | 417 | ||
472 | struct acx_energy_detection { | 418 | struct acx_energy_detection { |
@@ -969,6 +915,84 @@ struct wl1271_acx_pm_config { | |||
969 | u8 padding[3]; | 915 | u8 padding[3]; |
970 | } __attribute__ ((packed)); | 916 | } __attribute__ ((packed)); |
971 | 917 | ||
918 | struct wl1271_acx_keep_alive_mode { | ||
919 | struct acx_header header; | ||
920 | |||
921 | u8 enabled; | ||
922 | u8 padding[3]; | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | enum { | ||
926 | ACX_KEEP_ALIVE_NO_TX = 0, | ||
927 | ACX_KEEP_ALIVE_PERIOD_ONLY | ||
928 | }; | ||
929 | |||
930 | enum { | ||
931 | ACX_KEEP_ALIVE_TPL_INVALID = 0, | ||
932 | ACX_KEEP_ALIVE_TPL_VALID | ||
933 | }; | ||
934 | |||
935 | struct wl1271_acx_keep_alive_config { | ||
936 | struct acx_header header; | ||
937 | |||
938 | __le32 period; | ||
939 | u8 index; | ||
940 | u8 tpl_validation; | ||
941 | u8 trigger; | ||
942 | u8 padding; | ||
943 | } __attribute__ ((packed)); | ||
944 | |||
945 | enum { | ||
946 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, | ||
947 | WL1271_ACX_TRIG_TYPE_EDGE, | ||
948 | }; | ||
949 | |||
950 | enum { | ||
951 | WL1271_ACX_TRIG_DIR_LOW = 0, | ||
952 | WL1271_ACX_TRIG_DIR_HIGH, | ||
953 | WL1271_ACX_TRIG_DIR_BIDIR, | ||
954 | }; | ||
955 | |||
956 | enum { | ||
957 | WL1271_ACX_TRIG_ENABLE = 1, | ||
958 | WL1271_ACX_TRIG_DISABLE, | ||
959 | }; | ||
960 | |||
961 | enum { | ||
962 | WL1271_ACX_TRIG_METRIC_RSSI_BEACON = 0, | ||
963 | WL1271_ACX_TRIG_METRIC_RSSI_DATA, | ||
964 | WL1271_ACX_TRIG_METRIC_SNR_BEACON, | ||
965 | WL1271_ACX_TRIG_METRIC_SNR_DATA, | ||
966 | }; | ||
967 | |||
968 | enum { | ||
969 | WL1271_ACX_TRIG_IDX_RSSI = 0, | ||
970 | WL1271_ACX_TRIG_COUNT = 8, | ||
971 | }; | ||
972 | |||
973 | struct wl1271_acx_rssi_snr_trigger { | ||
974 | struct acx_header header; | ||
975 | |||
976 | __le16 threshold; | ||
977 | __le16 pacing; /* 0 - 60000 ms */ | ||
978 | u8 metric; | ||
979 | u8 type; | ||
980 | u8 dir; | ||
981 | u8 hysteresis; | ||
982 | u8 index; | ||
983 | u8 enable; | ||
984 | u8 padding[2]; | ||
985 | }; | ||
986 | |||
987 | struct wl1271_acx_rssi_snr_avg_weights { | ||
988 | struct acx_header header; | ||
989 | |||
990 | u8 rssi_beacon; | ||
991 | u8 rssi_data; | ||
992 | u8 snr_beacon; | ||
993 | u8 snr_data; | ||
994 | }; | ||
995 | |||
972 | enum { | 996 | enum { |
973 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 997 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
974 | ACX_MEM_CFG = 0x0003, | 998 | ACX_MEM_CFG = 0x0003, |
@@ -1017,8 +1041,8 @@ enum { | |||
1017 | ACX_FRAG_CFG = 0x004F, | 1041 | ACX_FRAG_CFG = 0x004F, |
1018 | ACX_BET_ENABLE = 0x0050, | 1042 | ACX_BET_ENABLE = 0x0050, |
1019 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 1043 | ACX_RSSI_SNR_TRIGGER = 0x0051, |
1020 | ACX_RSSI_SNR_WEIGHTS = 0x0051, | 1044 | ACX_RSSI_SNR_WEIGHTS = 0x0052, |
1021 | ACX_KEEP_ALIVE_MODE = 0x0052, | 1045 | ACX_KEEP_ALIVE_MODE = 0x0053, |
1022 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1046 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
1023 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 1047 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, |
1024 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 1048 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, |
@@ -1058,8 +1082,8 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | |||
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1082 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1083 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1084 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1085 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1062 | int wl1271_acx_sg_enable(struct wl1271 *wl); | 1086 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1063 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1087 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1064 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1088 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
1065 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); | 1089 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); |
@@ -1085,5 +1109,10 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | |||
1085 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1109 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1086 | u8 version); | 1110 | u8 version); |
1087 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1111 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1112 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | ||
1113 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | ||
1114 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1115 | s16 thold, u8 hyst); | ||
1116 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); | ||
1088 | 1117 | ||
1089 | #endif /* __WL1271_ACX_H__ */ | 1118 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 024356263065..1a36d8a2196e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -27,7 +27,6 @@ | |||
27 | #include "wl1271_acx.h" | 27 | #include "wl1271_acx.h" |
28 | #include "wl1271_reg.h" | 28 | #include "wl1271_reg.h" |
29 | #include "wl1271_boot.h" | 29 | #include "wl1271_boot.h" |
30 | #include "wl1271_spi.h" | ||
31 | #include "wl1271_io.h" | 30 | #include "wl1271_io.h" |
32 | #include "wl1271_event.h" | 31 | #include "wl1271_event.h" |
33 | 32 | ||
@@ -230,6 +229,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
230 | nvs_len = sizeof(wl->nvs->nvs); | 229 | nvs_len = sizeof(wl->nvs->nvs); |
231 | nvs_ptr = (u8 *)wl->nvs->nvs; | 230 | nvs_ptr = (u8 *)wl->nvs->nvs; |
232 | 231 | ||
232 | /* update current MAC address to NVS */ | ||
233 | nvs_ptr[11] = wl->mac_addr[0]; | ||
234 | nvs_ptr[10] = wl->mac_addr[1]; | ||
235 | nvs_ptr[6] = wl->mac_addr[2]; | ||
236 | nvs_ptr[5] = wl->mac_addr[3]; | ||
237 | nvs_ptr[4] = wl->mac_addr[4]; | ||
238 | nvs_ptr[3] = wl->mac_addr[5]; | ||
239 | |||
233 | /* | 240 | /* |
234 | * Layout before the actual NVS tables: | 241 | * Layout before the actual NVS tables: |
235 | * 1 byte : burst length. | 242 | * 1 byte : burst length. |
@@ -300,7 +307,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
300 | 307 | ||
301 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 308 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
302 | { | 309 | { |
303 | enable_irq(wl->irq); | 310 | wl1271_enable_interrupts(wl); |
304 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 311 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
305 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 312 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
306 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 313 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
@@ -344,7 +351,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
344 | static int wl1271_boot_run_firmware(struct wl1271 *wl) | 351 | static int wl1271_boot_run_firmware(struct wl1271 *wl) |
345 | { | 352 | { |
346 | int loop, ret; | 353 | int loop, ret; |
347 | u32 chip_id, interrupt; | 354 | u32 chip_id, intr; |
348 | 355 | ||
349 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 356 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
350 | 357 | ||
@@ -361,15 +368,15 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
361 | loop = 0; | 368 | loop = 0; |
362 | while (loop++ < INIT_LOOP) { | 369 | while (loop++ < INIT_LOOP) { |
363 | udelay(INIT_LOOP_DELAY); | 370 | udelay(INIT_LOOP_DELAY); |
364 | interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 371 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
365 | 372 | ||
366 | if (interrupt == 0xffffffff) { | 373 | if (intr == 0xffffffff) { |
367 | wl1271_error("error reading hardware complete " | 374 | wl1271_error("error reading hardware complete " |
368 | "init indication"); | 375 | "init indication"); |
369 | return -EIO; | 376 | return -EIO; |
370 | } | 377 | } |
371 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 378 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
372 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { | 379 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { |
373 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, | 380 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
374 | WL1271_ACX_INTR_INIT_COMPLETE); | 381 | WL1271_ACX_INTR_INIT_COMPLETE); |
375 | break; | 382 | break; |
@@ -404,7 +411,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
404 | /* unmask required mbox events */ | 411 | /* unmask required mbox events */ |
405 | wl->event_mask = BSS_LOSE_EVENT_ID | | 412 | wl->event_mask = BSS_LOSE_EVENT_ID | |
406 | SCAN_COMPLETE_EVENT_ID | | 413 | SCAN_COMPLETE_EVENT_ID | |
407 | PS_REPORT_EVENT_ID; | 414 | PS_REPORT_EVENT_ID | |
415 | JOIN_EVENT_COMPLETE_ID | | ||
416 | DISCONNECT_EVENT_COMPLETE_ID | | ||
417 | RSSI_SNR_TRIGGER_0_EVENT_ID; | ||
408 | 418 | ||
409 | ret = wl1271_event_unmask(wl); | 419 | ret = wl1271_event_unmask(wl); |
410 | if (ret < 0) { | 420 | if (ret < 0) { |
@@ -431,11 +441,23 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) | |||
431 | return 0; | 441 | return 0; |
432 | } | 442 | } |
433 | 443 | ||
444 | static void wl1271_boot_hw_version(struct wl1271 *wl) | ||
445 | { | ||
446 | u32 fuse; | ||
447 | |||
448 | fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); | ||
449 | fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; | ||
450 | |||
451 | wl->hw_pg_ver = (s8)fuse; | ||
452 | } | ||
453 | |||
434 | int wl1271_boot(struct wl1271 *wl) | 454 | int wl1271_boot(struct wl1271 *wl) |
435 | { | 455 | { |
436 | int ret = 0; | 456 | int ret = 0; |
437 | u32 tmp, clk, pause; | 457 | u32 tmp, clk, pause; |
438 | 458 | ||
459 | wl1271_boot_hw_version(wl); | ||
460 | |||
439 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) | 461 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) |
440 | /* ref clk: 19.2/38.4/38.4-XTAL */ | 462 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
441 | clk = 0x3; | 463 | clk = 0x3; |
@@ -445,11 +467,15 @@ int wl1271_boot(struct wl1271 *wl) | |||
445 | 467 | ||
446 | if (REF_CLOCK != 0) { | 468 | if (REF_CLOCK != 0) { |
447 | u16 val; | 469 | u16 val; |
448 | /* Set clock type */ | 470 | /* Set clock type (open drain) */ |
449 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 471 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
450 | val &= FREF_CLK_TYPE_BITS; | 472 | val &= FREF_CLK_TYPE_BITS; |
451 | val |= CLK_REQ_PRCM; | ||
452 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 473 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
474 | |||
475 | /* Set clock pull mode (no pull) */ | ||
476 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
477 | val |= NO_PULL; | ||
478 | wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
453 | } else { | 479 | } else { |
454 | u16 val; | 480 | u16 val; |
455 | /* Set clock polarity */ | 481 | /* Set clock polarity */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 412443ee655a..f829699d597e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -53,10 +53,16 @@ struct wl1271_static_data { | |||
53 | #define OCP_REG_POLARITY 0x0064 | 53 | #define OCP_REG_POLARITY 0x0064 |
54 | #define OCP_REG_CLK_TYPE 0x0448 | 54 | #define OCP_REG_CLK_TYPE 0x0448 |
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
56 | 57 | ||
57 | #define CMD_MBOX_ADDRESS 0x407B4 | 58 | #define REG_FUSE_DATA_2_1 0x050a |
59 | #define PG_VER_MASK 0x3c | ||
60 | #define PG_VER_OFFSET 2 | ||
58 | 61 | ||
59 | #define POLARITY_LOW BIT(1) | 62 | #define CMD_MBOX_ADDRESS 0x407B4 |
63 | |||
64 | #define POLARITY_LOW BIT(1) | ||
65 | #define NO_PULL (BIT(14) | BIT(15)) | ||
60 | 66 | ||
61 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | 67 | #define FREF_CLK_TYPE_BITS 0xfffffe7f |
62 | #define CLK_REQ_PRCM 0x100 | 68 | #define CLK_REQ_PRCM 0x100 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index e7832f3318eb..19393e236e2c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -26,15 +26,18 @@ | |||
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
29 | #include <linux/ieee80211.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | 31 | ||
31 | #include "wl1271.h" | 32 | #include "wl1271.h" |
32 | #include "wl1271_reg.h" | 33 | #include "wl1271_reg.h" |
33 | #include "wl1271_spi.h" | ||
34 | #include "wl1271_io.h" | 34 | #include "wl1271_io.h" |
35 | #include "wl1271_acx.h" | 35 | #include "wl1271_acx.h" |
36 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
37 | #include "wl1271_cmd.h" | 37 | #include "wl1271_cmd.h" |
38 | #include "wl1271_event.h" | ||
39 | |||
40 | #define WL1271_CMD_FAST_POLL_COUNT 50 | ||
38 | 41 | ||
39 | /* | 42 | /* |
40 | * send command to firmware | 43 | * send command to firmware |
@@ -52,6 +55,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
52 | u32 intr; | 55 | u32 intr; |
53 | int ret = 0; | 56 | int ret = 0; |
54 | u16 status; | 57 | u16 status; |
58 | u16 poll_count = 0; | ||
55 | 59 | ||
56 | cmd = buf; | 60 | cmd = buf; |
57 | cmd->id = cpu_to_le16(id); | 61 | cmd->id = cpu_to_le16(id); |
@@ -73,7 +77,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
73 | goto out; | 77 | goto out; |
74 | } | 78 | } |
75 | 79 | ||
76 | msleep(1); | 80 | poll_count++; |
81 | if (poll_count < WL1271_CMD_FAST_POLL_COUNT) | ||
82 | udelay(10); | ||
83 | else | ||
84 | msleep(1); | ||
77 | 85 | ||
78 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 86 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
79 | } | 87 | } |
@@ -249,7 +257,36 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
249 | return ret; | 257 | return ret; |
250 | } | 258 | } |
251 | 259 | ||
252 | int wl1271_cmd_join(struct wl1271 *wl) | 260 | /* |
261 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
262 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | ||
263 | */ | ||
264 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
265 | { | ||
266 | u32 events_vector, event; | ||
267 | unsigned long timeout; | ||
268 | |||
269 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | ||
270 | |||
271 | do { | ||
272 | if (time_after(jiffies, timeout)) | ||
273 | return -ETIMEDOUT; | ||
274 | |||
275 | msleep(1); | ||
276 | |||
277 | /* read from both event fields */ | ||
278 | wl1271_read(wl, wl->mbox_ptr[0], &events_vector, | ||
279 | sizeof(events_vector), false); | ||
280 | event = events_vector & mask; | ||
281 | wl1271_read(wl, wl->mbox_ptr[1], &events_vector, | ||
282 | sizeof(events_vector), false); | ||
283 | event |= events_vector & mask; | ||
284 | } while (!event); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | ||
253 | { | 290 | { |
254 | static bool do_cal = true; | 291 | static bool do_cal = true; |
255 | struct wl1271_cmd_join *join; | 292 | struct wl1271_cmd_join *join; |
@@ -280,30 +317,13 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
280 | 317 | ||
281 | join->rx_config_options = cpu_to_le32(wl->rx_config); | 318 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
282 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); | 319 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
283 | join->bss_type = wl->bss_type; | 320 | join->bss_type = bss_type; |
321 | join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); | ||
284 | 322 | ||
285 | /* | 323 | if (wl->band == IEEE80211_BAND_5GHZ) |
286 | * FIXME: disable temporarily all filters because after commit | ||
287 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
288 | * association. The filter logic needs to be implemented properly | ||
289 | * and once that is done, this hack can be removed. | ||
290 | */ | ||
291 | join->rx_config_options = cpu_to_le32(0); | ||
292 | join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); | ||
293 | |||
294 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
295 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | ||
296 | CONF_HW_BIT_RATE_2MBPS | | ||
297 | CONF_HW_BIT_RATE_5_5MBPS | | ||
298 | CONF_HW_BIT_RATE_11MBPS); | ||
299 | else { | ||
300 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | 324 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; |
301 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | | ||
302 | CONF_HW_BIT_RATE_12MBPS | | ||
303 | CONF_HW_BIT_RATE_24MBPS); | ||
304 | } | ||
305 | 325 | ||
306 | join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); | 326 | join->beacon_interval = cpu_to_le16(wl->beacon_int); |
307 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | 327 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; |
308 | 328 | ||
309 | join->channel = wl->channel; | 329 | join->channel = wl->channel; |
@@ -320,8 +340,7 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
320 | 340 | ||
321 | /* reset TX security counters */ | 341 | /* reset TX security counters */ |
322 | wl->tx_security_last_seq = 0; | 342 | wl->tx_security_last_seq = 0; |
323 | wl->tx_security_seq_16 = 0; | 343 | wl->tx_security_seq = 0; |
324 | wl->tx_security_seq_32 = 0; | ||
325 | 344 | ||
326 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); | 345 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); |
327 | if (ret < 0) { | 346 | if (ret < 0) { |
@@ -329,11 +348,9 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
329 | goto out_free; | 348 | goto out_free; |
330 | } | 349 | } |
331 | 350 | ||
332 | /* | 351 | ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); |
333 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 352 | if (ret < 0) |
334 | * simplify locking we just sleep instead, for now | 353 | wl1271_error("cmd join event completion error"); |
335 | */ | ||
336 | msleep(10); | ||
337 | 354 | ||
338 | out_free: | 355 | out_free: |
339 | kfree(join); | 356 | kfree(join); |
@@ -465,7 +482,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) | |||
465 | if (ret < 0) { | 482 | if (ret < 0) { |
466 | wl1271_error("tx %s cmd for channel %d failed", | 483 | wl1271_error("tx %s cmd for channel %d failed", |
467 | enable ? "start" : "stop", cmd->channel); | 484 | enable ? "start" : "stop", cmd->channel); |
468 | return ret; | 485 | goto out; |
469 | } | 486 | } |
470 | 487 | ||
471 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 488 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
@@ -499,7 +516,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | |||
499 | ps_params->ps_mode = ps_mode; | 516 | ps_params->ps_mode = ps_mode; |
500 | ps_params->send_null_data = send; | 517 | ps_params->send_null_data = send; |
501 | ps_params->retries = 5; | 518 | ps_params->retries = 5; |
502 | ps_params->hang_over_period = 128; | 519 | ps_params->hang_over_period = 1; |
503 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ | 520 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ |
504 | 521 | ||
505 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 522 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
@@ -549,25 +566,29 @@ out: | |||
549 | return ret; | 566 | return ret; |
550 | } | 567 | } |
551 | 568 | ||
552 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 569 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
553 | u8 active_scan, u8 high_prio, u8 band, | 570 | const u8 *ie, size_t ie_len, u8 active_scan, |
554 | u8 probe_requests) | 571 | u8 high_prio, u8 band, u8 probe_requests) |
555 | { | 572 | { |
556 | 573 | ||
557 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 574 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
558 | struct wl1271_cmd_scan *params = NULL; | 575 | struct wl1271_cmd_scan *params = NULL; |
559 | struct ieee80211_channel *channels; | 576 | struct ieee80211_channel *channels; |
577 | u32 rate; | ||
560 | int i, j, n_ch, ret; | 578 | int i, j, n_ch, ret; |
561 | u16 scan_options = 0; | 579 | u16 scan_options = 0; |
562 | u8 ieee_band; | 580 | u8 ieee_band; |
563 | 581 | ||
564 | if (band == WL1271_SCAN_BAND_2_4_GHZ) | 582 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { |
565 | ieee_band = IEEE80211_BAND_2GHZ; | 583 | ieee_band = IEEE80211_BAND_2GHZ; |
566 | else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) | 584 | rate = wl->conf.tx.basic_rate; |
585 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
567 | ieee_band = IEEE80211_BAND_2GHZ; | 586 | ieee_band = IEEE80211_BAND_2GHZ; |
568 | else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) | 587 | rate = wl->conf.tx.basic_rate; |
588 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
569 | ieee_band = IEEE80211_BAND_5GHZ; | 589 | ieee_band = IEEE80211_BAND_5GHZ; |
570 | else | 590 | rate = wl->conf.tx.basic_rate_5; |
591 | } else | ||
571 | return -EINVAL; | 592 | return -EINVAL; |
572 | 593 | ||
573 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | 594 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) |
@@ -594,8 +615,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
594 | params->params.scan_options = cpu_to_le16(scan_options); | 615 | params->params.scan_options = cpu_to_le16(scan_options); |
595 | 616 | ||
596 | params->params.num_probe_requests = probe_requests; | 617 | params->params.num_probe_requests = probe_requests; |
597 | /* Let the fw autodetect suitable tx_rate for probes */ | 618 | params->params.tx_rate = cpu_to_le32(rate); |
598 | params->params.tx_rate = 0; | ||
599 | params->params.tid_trigger = 0; | 619 | params->params.tid_trigger = 0; |
600 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 620 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
601 | 621 | ||
@@ -622,12 +642,13 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
622 | 642 | ||
623 | params->params.num_channels = j; | 643 | params->params.num_channels = j; |
624 | 644 | ||
625 | if (len && ssid) { | 645 | if (ssid_len && ssid) { |
626 | params->params.ssid_len = len; | 646 | params->params.ssid_len = ssid_len; |
627 | memcpy(params->params.ssid, ssid, len); | 647 | memcpy(params->params.ssid, ssid, ssid_len); |
628 | } | 648 | } |
629 | 649 | ||
630 | ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); | 650 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, |
651 | ie, ie_len, ieee_band); | ||
631 | if (ret < 0) { | 652 | if (ret < 0) { |
632 | wl1271_error("PROBE request template failed"); | 653 | wl1271_error("PROBE request template failed"); |
633 | goto out; | 654 | goto out; |
@@ -658,9 +679,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
658 | wl->scan.active = active_scan; | 679 | wl->scan.active = active_scan; |
659 | wl->scan.high_prio = high_prio; | 680 | wl->scan.high_prio = high_prio; |
660 | wl->scan.probe_requests = probe_requests; | 681 | wl->scan.probe_requests = probe_requests; |
661 | if (len && ssid) { | 682 | if (ssid_len && ssid) { |
662 | wl->scan.ssid_len = len; | 683 | wl->scan.ssid_len = ssid_len; |
663 | memcpy(wl->scan.ssid, ssid, len); | 684 | memcpy(wl->scan.ssid, ssid, ssid_len); |
664 | } else | 685 | } else |
665 | wl->scan.ssid_len = 0; | 686 | wl->scan.ssid_len = 0; |
666 | } | 687 | } |
@@ -675,11 +696,12 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
675 | 696 | ||
676 | out: | 697 | out: |
677 | kfree(params); | 698 | kfree(params); |
699 | kfree(trigger); | ||
678 | return ret; | 700 | return ret; |
679 | } | 701 | } |
680 | 702 | ||
681 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 703 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
682 | void *buf, size_t buf_len) | 704 | void *buf, size_t buf_len, int index, u32 rates) |
683 | { | 705 | { |
684 | struct wl1271_cmd_template_set *cmd; | 706 | struct wl1271_cmd_template_set *cmd; |
685 | int ret = 0; | 707 | int ret = 0; |
@@ -697,9 +719,10 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
697 | 719 | ||
698 | cmd->len = cpu_to_le16(buf_len); | 720 | cmd->len = cpu_to_le16(buf_len); |
699 | cmd->template_type = template_id; | 721 | cmd->template_type = template_id; |
700 | cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); | 722 | cmd->enabled_rates = cpu_to_le32(rates); |
701 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; | 723 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; |
702 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; | 724 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; |
725 | cmd->index = index; | ||
703 | 726 | ||
704 | if (buf) | 727 | if (buf) |
705 | memcpy(cmd->template_data, buf, buf_len); | 728 | memcpy(cmd->template_data, buf, buf_len); |
@@ -717,155 +740,129 @@ out: | |||
717 | return ret; | 740 | return ret; |
718 | } | 741 | } |
719 | 742 | ||
720 | static int wl1271_build_basic_rates(u8 *rates, u8 band) | 743 | int wl1271_cmd_build_null_data(struct wl1271 *wl) |
721 | { | 744 | { |
722 | u8 index = 0; | 745 | struct sk_buff *skb = NULL; |
723 | 746 | int size; | |
724 | if (band == IEEE80211_BAND_2GHZ) { | 747 | void *ptr; |
725 | rates[index++] = | 748 | int ret = -ENOMEM; |
726 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | ||
727 | rates[index++] = | ||
728 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
729 | rates[index++] = | ||
730 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
731 | rates[index++] = | ||
732 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
733 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
734 | rates[index++] = | ||
735 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; | ||
736 | rates[index++] = | ||
737 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; | ||
738 | rates[index++] = | ||
739 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
740 | } else { | ||
741 | wl1271_error("build_basic_rates invalid band: %d", band); | ||
742 | } | ||
743 | 749 | ||
744 | return index; | ||
745 | } | ||
746 | 750 | ||
747 | static int wl1271_build_extended_rates(u8 *rates, u8 band) | 751 | if (wl->bss_type == BSS_TYPE_IBSS) { |
748 | { | 752 | size = sizeof(struct wl12xx_null_data_template); |
749 | u8 index = 0; | 753 | ptr = NULL; |
750 | |||
751 | if (band == IEEE80211_BAND_2GHZ) { | ||
752 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | ||
753 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | ||
754 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | ||
755 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | ||
756 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | ||
757 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | ||
758 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | ||
759 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
760 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
761 | rates[index++] = | ||
762 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; | ||
763 | rates[index++] = | ||
764 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; | ||
765 | rates[index++] = | ||
766 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
767 | rates[index++] = | ||
768 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; | ||
769 | rates[index++] = | ||
770 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; | ||
771 | rates[index++] = | ||
772 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; | ||
773 | } else { | 754 | } else { |
774 | wl1271_error("build_basic_rates invalid band: %d", band); | 755 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
756 | if (!skb) | ||
757 | goto out; | ||
758 | size = skb->len; | ||
759 | ptr = skb->data; | ||
775 | } | 760 | } |
776 | 761 | ||
777 | return index; | 762 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
763 | WL1271_RATE_AUTOMATIC); | ||
764 | |||
765 | out: | ||
766 | dev_kfree_skb(skb); | ||
767 | if (ret) | ||
768 | wl1271_warning("cmd buld null data failed %d", ret); | ||
769 | |||
770 | return ret; | ||
771 | |||
778 | } | 772 | } |
779 | 773 | ||
780 | int wl1271_cmd_build_null_data(struct wl1271 *wl) | 774 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) |
781 | { | 775 | { |
782 | struct wl12xx_null_data_template template; | 776 | struct sk_buff *skb = NULL; |
777 | int ret = -ENOMEM; | ||
783 | 778 | ||
784 | if (!is_zero_ether_addr(wl->bssid)) { | 779 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
785 | memcpy(template.header.da, wl->bssid, ETH_ALEN); | 780 | if (!skb) |
786 | memcpy(template.header.bssid, wl->bssid, ETH_ALEN); | 781 | goto out; |
787 | } else { | 782 | |
788 | memset(template.header.da, 0xff, ETH_ALEN); | 783 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, |
789 | memset(template.header.bssid, 0xff, ETH_ALEN); | 784 | skb->data, skb->len, |
790 | } | 785 | CMD_TEMPL_KLV_IDX_NULL_DATA, |
786 | WL1271_RATE_AUTOMATIC); | ||
791 | 787 | ||
792 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 788 | out: |
793 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | 789 | dev_kfree_skb(skb); |
794 | IEEE80211_STYPE_NULLFUNC | | 790 | if (ret) |
795 | IEEE80211_FCTL_TODS); | 791 | wl1271_warning("cmd build klv null data failed %d", ret); |
796 | 792 | ||
797 | return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, | 793 | return ret; |
798 | sizeof(template)); | ||
799 | 794 | ||
800 | } | 795 | } |
801 | 796 | ||
802 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 797 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) |
803 | { | 798 | { |
804 | struct wl12xx_ps_poll_template template; | 799 | struct sk_buff *skb; |
805 | 800 | int ret = 0; | |
806 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | ||
807 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | ||
808 | |||
809 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
810 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | ||
811 | 801 | ||
812 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 802 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); |
803 | if (!skb) | ||
804 | goto out; | ||
813 | 805 | ||
814 | return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, | 806 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
815 | sizeof(template)); | 807 | skb->len, 0, wl->basic_rate); |
816 | 808 | ||
809 | out: | ||
810 | dev_kfree_skb(skb); | ||
811 | return ret; | ||
817 | } | 812 | } |
818 | 813 | ||
819 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, | 814 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
820 | u8 band) | 815 | const u8 *ssid, size_t ssid_len, |
816 | const u8 *ie, size_t ie_len, u8 band) | ||
821 | { | 817 | { |
822 | struct wl12xx_probe_req_template template; | 818 | struct sk_buff *skb; |
823 | struct wl12xx_ie_rates *rates; | ||
824 | char *ptr; | ||
825 | u16 size; | ||
826 | int ret; | 819 | int ret; |
827 | 820 | ||
828 | ptr = (char *)&template; | 821 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
829 | size = sizeof(struct ieee80211_header); | 822 | ie, ie_len); |
830 | 823 | if (!skb) { | |
831 | memset(template.header.da, 0xff, ETH_ALEN); | 824 | ret = -ENOMEM; |
832 | memset(template.header.bssid, 0xff, ETH_ALEN); | 825 | goto out; |
833 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 826 | } |
834 | template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 827 | |
835 | 828 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | |
836 | /* IEs */ | ||
837 | /* SSID */ | ||
838 | template.ssid.header.id = WLAN_EID_SSID; | ||
839 | template.ssid.header.len = ssid_len; | ||
840 | if (ssid_len && ssid) | ||
841 | memcpy(template.ssid.ssid, ssid, ssid_len); | ||
842 | size += sizeof(struct wl12xx_ie_header) + ssid_len; | ||
843 | ptr += size; | ||
844 | |||
845 | /* Basic Rates */ | ||
846 | rates = (struct wl12xx_ie_rates *)ptr; | ||
847 | rates->header.id = WLAN_EID_SUPP_RATES; | ||
848 | rates->header.len = wl1271_build_basic_rates(rates->rates, band); | ||
849 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
850 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
851 | |||
852 | /* Extended rates */ | ||
853 | rates = (struct wl12xx_ie_rates *)ptr; | ||
854 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | ||
855 | rates->header.len = wl1271_build_extended_rates(rates->rates, band); | ||
856 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
857 | |||
858 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | ||
859 | 829 | ||
860 | if (band == IEEE80211_BAND_2GHZ) | 830 | if (band == IEEE80211_BAND_2GHZ) |
861 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 831 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
862 | &template, size); | 832 | skb->data, skb->len, 0, |
833 | wl->conf.tx.basic_rate); | ||
863 | else | 834 | else |
864 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 835 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
865 | &template, size); | 836 | skb->data, skb->len, 0, |
837 | wl->conf.tx.basic_rate_5); | ||
838 | |||
839 | out: | ||
840 | dev_kfree_skb(skb); | ||
866 | return ret; | 841 | return ret; |
867 | } | 842 | } |
868 | 843 | ||
844 | int wl1271_build_qos_null_data(struct wl1271 *wl) | ||
845 | { | ||
846 | struct ieee80211_qos_hdr template; | ||
847 | |||
848 | memset(&template, 0, sizeof(template)); | ||
849 | |||
850 | memcpy(template.addr1, wl->bssid, ETH_ALEN); | ||
851 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); | ||
852 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
853 | |||
854 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
855 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
856 | IEEE80211_FCTL_TODS); | ||
857 | |||
858 | /* FIXME: not sure what priority to use here */ | ||
859 | template.qos_ctrl = cpu_to_le16(0); | ||
860 | |||
861 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | ||
862 | sizeof(template), 0, | ||
863 | WL1271_RATE_AUTOMATIC); | ||
864 | } | ||
865 | |||
869 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 866 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
870 | { | 867 | { |
871 | struct wl1271_cmd_set_keys *cmd; | 868 | struct wl1271_cmd_set_keys *cmd; |
@@ -976,6 +973,10 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) | |||
976 | goto out_free; | 973 | goto out_free; |
977 | } | 974 | } |
978 | 975 | ||
976 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | ||
977 | if (ret < 0) | ||
978 | wl1271_error("cmd disconnect event completion error"); | ||
979 | |||
979 | out_free: | 980 | out_free: |
980 | kfree(cmd); | 981 | kfree(cmd); |
981 | 982 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 2dc06c73532b..f2820b42a943 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -33,7 +33,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wl1271_cmd_general_parms(struct wl1271 *wl); | 34 | int wl1271_cmd_general_parms(struct wl1271 *wl); |
35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | 35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); |
36 | int wl1271_cmd_join(struct wl1271 *wl); | 36 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); |
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
@@ -41,15 +41,18 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | |||
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
45 | u8 active_scan, u8 high_prio, u8 band, | 45 | const u8 *ie, size_t ie_len, u8 active_scan, |
46 | u8 probe_requests); | 46 | u8 high_prio, u8 band, u8 probe_requests); |
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len); | 48 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | 50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); |
51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, | 51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
52 | u8 band); | 52 | const u8 *ssid, size_t ssid_len, |
53 | const u8 *ie, size_t ie_len, u8 band); | ||
54 | int wl1271_build_qos_null_data(struct wl1271 *wl); | ||
55 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | ||
53 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 56 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
54 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 57 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
55 | u8 key_size, const u8 *key, const u8 *addr, | 58 | u8 key_size, const u8 *key, const u8 *addr, |
@@ -99,6 +102,11 @@ enum wl1271_commands { | |||
99 | 102 | ||
100 | #define MAX_CMD_PARAMS 572 | 103 | #define MAX_CMD_PARAMS 572 |
101 | 104 | ||
105 | enum { | ||
106 | CMD_TEMPL_KLV_IDX_NULL_DATA = 0, | ||
107 | CMD_TEMPL_KLV_IDX_MAX = 4 | ||
108 | }; | ||
109 | |||
102 | enum cmd_templ { | 110 | enum cmd_templ { |
103 | CMD_TEMPL_NULL_DATA = 0, | 111 | CMD_TEMPL_NULL_DATA = 0, |
104 | CMD_TEMPL_BEACON, | 112 | CMD_TEMPL_BEACON, |
@@ -121,6 +129,7 @@ enum cmd_templ { | |||
121 | /* unit ms */ | 129 | /* unit ms */ |
122 | #define WL1271_COMMAND_TIMEOUT 2000 | 130 | #define WL1271_COMMAND_TIMEOUT 2000 |
123 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 | 131 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 |
132 | #define WL1271_EVENT_TIMEOUT 750 | ||
124 | 133 | ||
125 | struct wl1271_cmd_header { | 134 | struct wl1271_cmd_header { |
126 | __le16 id; | 135 | __le16 id; |
@@ -243,6 +252,8 @@ struct cmd_enabledisable_path { | |||
243 | u8 padding[3]; | 252 | u8 padding[3]; |
244 | } __attribute__ ((packed)); | 253 | } __attribute__ ((packed)); |
245 | 254 | ||
255 | #define WL1271_RATE_AUTOMATIC 0 | ||
256 | |||
246 | struct wl1271_cmd_template_set { | 257 | struct wl1271_cmd_template_set { |
247 | struct wl1271_cmd_header header; | 258 | struct wl1271_cmd_header header; |
248 | 259 | ||
@@ -509,6 +520,8 @@ enum wl1271_disconnect_type { | |||
509 | }; | 520 | }; |
510 | 521 | ||
511 | struct wl1271_cmd_disconnect { | 522 | struct wl1271_cmd_disconnect { |
523 | struct wl1271_cmd_header header; | ||
524 | |||
512 | __le32 rx_config_options; | 525 | __le32 rx_config_options; |
513 | __le32 rx_filter_options; | 526 | __le32 rx_filter_options; |
514 | 527 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 6f9e75cc5640..d046d044b5bd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -65,110 +65,344 @@ enum { | |||
65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, | 65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct conf_sg_settings { | 68 | enum { |
69 | CONF_HW_RXTX_RATE_MCS7 = 0, | ||
70 | CONF_HW_RXTX_RATE_MCS6, | ||
71 | CONF_HW_RXTX_RATE_MCS5, | ||
72 | CONF_HW_RXTX_RATE_MCS4, | ||
73 | CONF_HW_RXTX_RATE_MCS3, | ||
74 | CONF_HW_RXTX_RATE_MCS2, | ||
75 | CONF_HW_RXTX_RATE_MCS1, | ||
76 | CONF_HW_RXTX_RATE_MCS0, | ||
77 | CONF_HW_RXTX_RATE_54, | ||
78 | CONF_HW_RXTX_RATE_48, | ||
79 | CONF_HW_RXTX_RATE_36, | ||
80 | CONF_HW_RXTX_RATE_24, | ||
81 | CONF_HW_RXTX_RATE_22, | ||
82 | CONF_HW_RXTX_RATE_18, | ||
83 | CONF_HW_RXTX_RATE_12, | ||
84 | CONF_HW_RXTX_RATE_11, | ||
85 | CONF_HW_RXTX_RATE_9, | ||
86 | CONF_HW_RXTX_RATE_6, | ||
87 | CONF_HW_RXTX_RATE_5_5, | ||
88 | CONF_HW_RXTX_RATE_2, | ||
89 | CONF_HW_RXTX_RATE_1, | ||
90 | CONF_HW_RXTX_RATE_MAX, | ||
91 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | ||
92 | }; | ||
93 | |||
94 | enum { | ||
95 | CONF_SG_DISABLE = 0, | ||
96 | CONF_SG_PROTECTIVE, | ||
97 | CONF_SG_OPPORTUNISTIC | ||
98 | }; | ||
99 | |||
100 | enum { | ||
69 | /* | 101 | /* |
70 | * Defines the PER threshold in PPM of the BT voice of which reaching | 102 | * PER threshold in PPM of the BT voice |
71 | * this value will trigger raising the priority of the BT voice by | ||
72 | * the BT IP until next NFS sample interval time as defined in | ||
73 | * nfs_sample_interval. | ||
74 | * | 103 | * |
75 | * Unit: PER value in PPM (parts per million) | 104 | * Range: 0 - 10000000 |
76 | * #Error_packets / #Total_packets | 105 | */ |
106 | CONF_SG_BT_PER_THRESHOLD = 0, | ||
77 | 107 | ||
78 | * Range: u32 | 108 | /* |
109 | * Number of consequent RX_ACTIVE activities to override BT voice | ||
110 | * frames to ensure WLAN connection | ||
111 | * | ||
112 | * Range: 0 - 100 | ||
113 | */ | ||
114 | CONF_SG_HV3_MAX_OVERRIDE, | ||
115 | |||
116 | /* | ||
117 | * Defines the PER threshold of the BT voice | ||
118 | * | ||
119 | * Range: 0 - 65000 | ||
120 | */ | ||
121 | CONF_SG_BT_NFS_SAMPLE_INTERVAL, | ||
122 | |||
123 | /* | ||
124 | * Defines the load ratio of BT | ||
125 | * | ||
126 | * Range: 0 - 100 (%) | ||
127 | */ | ||
128 | CONF_SG_BT_LOAD_RATIO, | ||
129 | |||
130 | /* | ||
131 | * Defines whether the SG will force WLAN host to enter/exit PSM | ||
132 | * | ||
133 | * Range: 1 - SG can force, 0 - host handles PSM | ||
134 | */ | ||
135 | CONF_SG_AUTO_PS_MODE, | ||
136 | |||
137 | /* | ||
138 | * Compensation percentage of probe requests when scan initiated | ||
139 | * during BT voice/ACL link. | ||
140 | * | ||
141 | * Range: 0 - 255 (%) | ||
142 | */ | ||
143 | CONF_SG_AUTO_SCAN_PROBE_REQ, | ||
144 | |||
145 | /* | ||
146 | * Compensation percentage of probe requests when active scan initiated | ||
147 | * during BT voice | ||
148 | * | ||
149 | * Range: 0 - 255 (%) | ||
150 | */ | ||
151 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, | ||
152 | |||
153 | /* | ||
154 | * Defines antenna configuration (single/dual antenna) | ||
155 | * | ||
156 | * Range: 0 - single antenna, 1 - dual antenna | ||
157 | */ | ||
158 | CONF_SG_ANTENNA_CONFIGURATION, | ||
159 | |||
160 | /* | ||
161 | * The threshold (percent) of max consequtive beacon misses before | ||
162 | * increasing priority of beacon reception. | ||
163 | * | ||
164 | * Range: 0 - 100 (%) | ||
165 | */ | ||
166 | CONF_SG_BEACON_MISS_PERCENT, | ||
167 | |||
168 | /* | ||
169 | * The rate threshold below which receiving a data frame from the AP | ||
170 | * will increase the priority of the data frame above BT traffic. | ||
171 | * | ||
172 | * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 | ||
173 | */ | ||
174 | CONF_SG_RATE_ADAPT_THRESH, | ||
175 | |||
176 | /* | ||
177 | * Not used currently. | ||
178 | * | ||
179 | * Range: 0 | ||
180 | */ | ||
181 | CONF_SG_RATE_ADAPT_SNR, | ||
182 | |||
183 | /* | ||
184 | * Configure the min and max time BT gains the antenna | ||
185 | * in WLAN PSM / BT master basic rate | ||
186 | * | ||
187 | * Range: 0 - 255 (ms) | ||
188 | */ | ||
189 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, | ||
190 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, | ||
191 | |||
192 | /* | ||
193 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
194 | * in WLAN PSM / BT master basic rate | ||
195 | * | ||
196 | * Range: 0 - 255 (ms) | ||
197 | */ | ||
198 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, | ||
199 | |||
200 | /* | ||
201 | * Configure the min and max time BT gains the antenna | ||
202 | * in WLAN PSM / BT slave basic rate | ||
203 | * | ||
204 | * Range: 0 - 255 (ms) | ||
205 | */ | ||
206 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, | ||
207 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, | ||
208 | |||
209 | /* | ||
210 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
211 | * in WLAN PSM / BT slave basic rate | ||
212 | * | ||
213 | * Range: 0 - 255 (ms) | ||
214 | */ | ||
215 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, | ||
216 | |||
217 | /* | ||
218 | * Configure the min and max time BT gains the antenna | ||
219 | * in WLAN PSM / BT master EDR | ||
220 | * | ||
221 | * Range: 0 - 255 (ms) | ||
222 | */ | ||
223 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, | ||
224 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, | ||
225 | |||
226 | /* | ||
227 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
228 | * in WLAN PSM / BT master EDR | ||
229 | * | ||
230 | * Range: 0 - 255 (ms) | ||
231 | */ | ||
232 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, | ||
233 | |||
234 | /* | ||
235 | * Configure the min and max time BT gains the antenna | ||
236 | * in WLAN PSM / BT slave EDR | ||
237 | * | ||
238 | * Range: 0 - 255 (ms) | ||
239 | */ | ||
240 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, | ||
241 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, | ||
242 | |||
243 | /* | ||
244 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
245 | * in WLAN PSM / BT slave EDR | ||
246 | * | ||
247 | * Range: 0 - 255 (ms) | ||
248 | */ | ||
249 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, | ||
250 | |||
251 | /* | ||
252 | * RX guard time before the beginning of a new BT voice frame during | ||
253 | * which no new WLAN trigger frame is transmitted. | ||
254 | * | ||
255 | * Range: 0 - 100000 (us) | ||
256 | */ | ||
257 | CONF_SG_RXT, | ||
258 | |||
259 | /* | ||
260 | * TX guard time before the beginning of a new BT voice frame during | ||
261 | * which no new WLAN frame is transmitted. | ||
262 | * | ||
263 | * Range: 0 - 100000 (us) | ||
264 | */ | ||
265 | |||
266 | CONF_SG_TXT, | ||
267 | |||
268 | /* | ||
269 | * Enable adaptive RXT/TXT algorithm. If disabled, the host values | ||
270 | * will be utilized. | ||
271 | * | ||
272 | * Range: 0 - disable, 1 - enable | ||
273 | */ | ||
274 | CONF_SG_ADAPTIVE_RXT_TXT, | ||
275 | |||
276 | /* | ||
277 | * The used WLAN legacy service period during active BT ACL link | ||
278 | * | ||
279 | * Range: 0 - 255 (ms) | ||
280 | */ | ||
281 | CONF_SG_PS_POLL_TIMEOUT, | ||
282 | |||
283 | /* | ||
284 | * The used WLAN UPSD service period during active BT ACL link | ||
285 | * | ||
286 | * Range: 0 - 255 (ms) | ||
79 | */ | 287 | */ |
80 | u32 per_threshold; | 288 | CONF_SG_UPSD_TIMEOUT, |
81 | 289 | ||
82 | /* | 290 | /* |
83 | * This value is an absolute time in micro-seconds to limit the | 291 | * Configure the min and max time BT gains the antenna |
84 | * maximum scan duration compensation while in SG | 292 | * in WLAN Active / BT master EDR |
293 | * | ||
294 | * Range: 0 - 255 (ms) | ||
85 | */ | 295 | */ |
86 | u32 max_scan_compensation_time; | 296 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, |
297 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, | ||
87 | 298 | ||
88 | /* Defines the PER threshold of the BT voice of which reaching this | 299 | /* |
89 | * value will trigger raising the priority of the BT voice until next | 300 | * The maximum time WLAN can gain the antenna for |
90 | * NFS sample interval time as defined in sample_interval. | 301 | * in WLAN Active / BT master EDR |
91 | * | 302 | * |
92 | * Unit: msec | 303 | * Range: 0 - 255 (ms) |
93 | * Range: 1-65000 | ||
94 | */ | 304 | */ |
95 | u16 nfs_sample_interval; | 305 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, |
96 | 306 | ||
97 | /* | 307 | /* |
98 | * Defines the load ratio for the BT. | 308 | * Configure the min and max time BT gains the antenna |
99 | * The WLAN ratio is: 100 - load_ratio | 309 | * in WLAN Active / BT slave EDR |
100 | * | 310 | * |
101 | * Unit: Percent | 311 | * Range: 0 - 255 (ms) |
102 | * Range: 0-100 | ||
103 | */ | 312 | */ |
104 | u8 load_ratio; | 313 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, |
314 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, | ||
105 | 315 | ||
106 | /* | 316 | /* |
107 | * true - Co-ex is allowed to enter/exit P.S automatically and | 317 | * The maximum time WLAN can gain the antenna for |
108 | * transparently to the host | 318 | * in WLAN Active / BT slave EDR |
109 | * | 319 | * |
110 | * false - Co-ex is disallowed to enter/exit P.S and will trigger an | 320 | * Range: 0 - 255 (ms) |
111 | * event to the host to notify for the need to enter/exit P.S | 321 | */ |
112 | * due to BT change state | 322 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, |
323 | |||
324 | /* | ||
325 | * Configure the min and max time BT gains the antenna | ||
326 | * in WLAN Active / BT basic rate | ||
327 | * | ||
328 | * Range: 0 - 255 (ms) | ||
329 | */ | ||
330 | CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, | ||
331 | CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, | ||
332 | |||
333 | /* | ||
334 | * The maximum time WLAN can gain the antenna for | ||
335 | * in WLAN Active / BT basic rate | ||
113 | * | 336 | * |
337 | * Range: 0 - 255 (ms) | ||
114 | */ | 338 | */ |
115 | u8 auto_ps_mode; | 339 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, |
116 | 340 | ||
117 | /* | 341 | /* |
118 | * This parameter defines the compensation percentage of num of probe | 342 | * Compensation percentage of WLAN passive scan window if initiated |
119 | * requests in case scan is initiated during BT voice/BT ACL | 343 | * during BT voice |
120 | * guaranteed link. | ||
121 | * | 344 | * |
122 | * Unit: Percent | 345 | * Range: 0 - 1000 (%) |
123 | * Range: 0-255 (0 - No compensation) | ||
124 | */ | 346 | */ |
125 | u8 probe_req_compensation; | 347 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, |
126 | 348 | ||
127 | /* | 349 | /* |
128 | * This parameter defines the compensation percentage of scan window | 350 | * Compensation percentage of WLAN passive scan window if initiated |
129 | * size in case scan is initiated during BT voice/BT ACL Guaranteed | 351 | * during BT A2DP |
130 | * link. | ||
131 | * | 352 | * |
132 | * Unit: Percent | 353 | * Range: 0 - 1000 (%) |
133 | * Range: 0-255 (0 - No compensation) | ||
134 | */ | 354 | */ |
135 | u8 scan_window_compensation; | 355 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, |
136 | 356 | ||
137 | /* | 357 | /* |
138 | * Defines the antenna configuration. | 358 | * Fixed time ensured for BT traffic to gain the antenna during WLAN |
359 | * passive scan. | ||
139 | * | 360 | * |
140 | * Range: 0 - Single Antenna; 1 - Dual Antenna | 361 | * Range: 0 - 1000 ms |
141 | */ | 362 | */ |
142 | u8 antenna_config; | 363 | CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, |
143 | 364 | ||
144 | /* | 365 | /* |
145 | * The percent out of the Max consecutive beacon miss roaming trigger | 366 | * Fixed time ensured for WLAN traffic to gain the antenna during WLAN |
146 | * which is the threshold for raising the priority of beacon | 367 | * passive scan. |
147 | * reception. | ||
148 | * | 368 | * |
149 | * Range: 1-100 | 369 | * Range: 0 - 1000 ms |
150 | * N = MaxConsecutiveBeaconMiss | ||
151 | * P = coexMaxConsecutiveBeaconMissPrecent | ||
152 | * Threshold = MIN( N-1, round(N * P / 100)) | ||
153 | */ | 370 | */ |
154 | u8 beacon_miss_threshold; | 371 | CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, |
155 | 372 | ||
156 | /* | 373 | /* |
157 | * The RX rate threshold below which rate adaptation is assumed to be | 374 | * Number of consequent BT voice frames not interrupted by WLAN |
158 | * occurring at the AP which will raise priority for ACTIVE_RX and RX | ||
159 | * SP. | ||
160 | * | 375 | * |
161 | * Range: HW_BIT_RATE_* | 376 | * Range: 0 - 100 |
162 | */ | 377 | */ |
163 | u32 rate_adaptation_threshold; | 378 | CONF_SG_HV3_MAX_SERVED, |
164 | 379 | ||
165 | /* | 380 | /* |
166 | * The SNR above which the RX rate threshold indicating AP rate | 381 | * Protection time of the DHCP procedure. |
167 | * adaptation is valid | ||
168 | * | 382 | * |
169 | * Range: -128 - 127 | 383 | * Range: 0 - 100000 (ms) |
170 | */ | 384 | */ |
171 | s8 rate_adaptation_snr; | 385 | CONF_SG_DHCP_TIME, |
386 | |||
387 | /* | ||
388 | * Compensation percentage of WLAN active scan window if initiated | ||
389 | * during BT A2DP | ||
390 | * | ||
391 | * Range: 0 - 1000 (%) | ||
392 | */ | ||
393 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, | ||
394 | CONF_SG_TEMP_PARAM_1, | ||
395 | CONF_SG_TEMP_PARAM_2, | ||
396 | CONF_SG_TEMP_PARAM_3, | ||
397 | CONF_SG_TEMP_PARAM_4, | ||
398 | CONF_SG_TEMP_PARAM_5, | ||
399 | CONF_SG_PARAMS_MAX, | ||
400 | CONF_SG_PARAMS_ALL = 0xff | ||
401 | }; | ||
402 | |||
403 | struct conf_sg_settings { | ||
404 | u32 params[CONF_SG_PARAMS_MAX]; | ||
405 | u8 state; | ||
172 | }; | 406 | }; |
173 | 407 | ||
174 | enum conf_rx_queue_type { | 408 | enum conf_rx_queue_type { |
@@ -440,6 +674,19 @@ struct conf_tx_settings { | |||
440 | */ | 674 | */ |
441 | u16 tx_compl_threshold; | 675 | u16 tx_compl_threshold; |
442 | 676 | ||
677 | /* | ||
678 | * The rate used for control messages and scanning on the 2.4GHz band | ||
679 | * | ||
680 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
681 | */ | ||
682 | u32 basic_rate; | ||
683 | |||
684 | /* | ||
685 | * The rate used for control messages and scanning on the 5GHz band | ||
686 | * | ||
687 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
688 | */ | ||
689 | u32 basic_rate_5; | ||
443 | }; | 690 | }; |
444 | 691 | ||
445 | enum { | 692 | enum { |
@@ -509,65 +756,6 @@ enum { | |||
509 | CONF_TRIG_EVENT_DIR_BIDIR | 756 | CONF_TRIG_EVENT_DIR_BIDIR |
510 | }; | 757 | }; |
511 | 758 | ||
512 | |||
513 | struct conf_sig_trigger { | ||
514 | /* | ||
515 | * The RSSI / SNR threshold value. | ||
516 | * | ||
517 | * FIXME: what is the range? | ||
518 | */ | ||
519 | s16 threshold; | ||
520 | |||
521 | /* | ||
522 | * Minimum delay between two trigger events for this trigger in ms. | ||
523 | * | ||
524 | * Range: 0 - 60000 | ||
525 | */ | ||
526 | u16 pacing; | ||
527 | |||
528 | /* | ||
529 | * The measurement data source for this trigger. | ||
530 | * | ||
531 | * Range: CONF_TRIG_METRIC_* | ||
532 | */ | ||
533 | u8 metric; | ||
534 | |||
535 | /* | ||
536 | * The trigger type of this trigger. | ||
537 | * | ||
538 | * Range: CONF_TRIG_EVENT_TYPE_* | ||
539 | */ | ||
540 | u8 type; | ||
541 | |||
542 | /* | ||
543 | * The direction of the trigger. | ||
544 | * | ||
545 | * Range: CONF_TRIG_EVENT_DIR_* | ||
546 | */ | ||
547 | u8 direction; | ||
548 | |||
549 | /* | ||
550 | * Hysteresis range of the trigger around the threshold (in dB) | ||
551 | * | ||
552 | * Range: u8 | ||
553 | */ | ||
554 | u8 hysteresis; | ||
555 | |||
556 | /* | ||
557 | * Index of the trigger rule. | ||
558 | * | ||
559 | * Range: 0 - CONF_MAX_RSSI_SNR_TRIGGERS-1 | ||
560 | */ | ||
561 | u8 index; | ||
562 | |||
563 | /* | ||
564 | * Enable / disable this rule (to use for clearing rules.) | ||
565 | * | ||
566 | * Range: 1 - Enabled, 2 - Not enabled | ||
567 | */ | ||
568 | u8 enable; | ||
569 | }; | ||
570 | |||
571 | struct conf_sig_weights { | 759 | struct conf_sig_weights { |
572 | 760 | ||
573 | /* | 761 | /* |
@@ -686,12 +874,6 @@ struct conf_conn_settings { | |||
686 | u8 ps_poll_threshold; | 874 | u8 ps_poll_threshold; |
687 | 875 | ||
688 | /* | 876 | /* |
689 | * Configuration of signal (rssi/snr) triggers. | ||
690 | */ | ||
691 | u8 sig_trigger_count; | ||
692 | struct conf_sig_trigger sig_trigger[CONF_MAX_RSSI_SNR_TRIGGERS]; | ||
693 | |||
694 | /* | ||
695 | * Configuration of signal average weights. | 877 | * Configuration of signal average weights. |
696 | */ | 878 | */ |
697 | struct conf_sig_weights sig_weights; | 879 | struct conf_sig_weights sig_weights; |
@@ -721,6 +903,22 @@ struct conf_conn_settings { | |||
721 | * Range 0 - 255 | 903 | * Range 0 - 255 |
722 | */ | 904 | */ |
723 | u8 psm_entry_retries; | 905 | u8 psm_entry_retries; |
906 | |||
907 | /* | ||
908 | * | ||
909 | * Specifies the interval of the connection keep-alive null-func | ||
910 | * frame in ms. | ||
911 | * | ||
912 | * Range: 1000 - 3600000 | ||
913 | */ | ||
914 | u32 keep_alive_interval; | ||
915 | |||
916 | /* | ||
917 | * Maximum listen interval supported by the driver in units of beacons. | ||
918 | * | ||
919 | * Range: u16 | ||
920 | */ | ||
921 | u8 max_listen_interval; | ||
724 | }; | 922 | }; |
725 | 923 | ||
726 | enum { | 924 | enum { |
@@ -782,6 +980,43 @@ struct conf_pm_config_settings { | |||
782 | bool host_fast_wakeup_support; | 980 | bool host_fast_wakeup_support; |
783 | }; | 981 | }; |
784 | 982 | ||
983 | struct conf_roam_trigger_settings { | ||
984 | /* | ||
985 | * The minimum interval between two trigger events. | ||
986 | * | ||
987 | * Range: 0 - 60000 ms | ||
988 | */ | ||
989 | u16 trigger_pacing; | ||
990 | |||
991 | /* | ||
992 | * The weight for rssi/beacon average calculation | ||
993 | * | ||
994 | * Range: 0 - 255 | ||
995 | */ | ||
996 | u8 avg_weight_rssi_beacon; | ||
997 | |||
998 | /* | ||
999 | * The weight for rssi/data frame average calculation | ||
1000 | * | ||
1001 | * Range: 0 - 255 | ||
1002 | */ | ||
1003 | u8 avg_weight_rssi_data; | ||
1004 | |||
1005 | /* | ||
1006 | * The weight for snr/beacon average calculation | ||
1007 | * | ||
1008 | * Range: 0 - 255 | ||
1009 | */ | ||
1010 | u8 avg_weight_snr_beacon; | ||
1011 | |||
1012 | /* | ||
1013 | * The weight for snr/data frame average calculation | ||
1014 | * | ||
1015 | * Range: 0 - 255 | ||
1016 | */ | ||
1017 | u8 avg_weight_snr_data; | ||
1018 | }; | ||
1019 | |||
785 | struct conf_drv_settings { | 1020 | struct conf_drv_settings { |
786 | struct conf_sg_settings sg; | 1021 | struct conf_sg_settings sg; |
787 | struct conf_rx_settings rx; | 1022 | struct conf_rx_settings rx; |
@@ -790,6 +1025,7 @@ struct conf_drv_settings { | |||
790 | struct conf_init_settings init; | 1025 | struct conf_init_settings init; |
791 | struct conf_itrim_settings itrim; | 1026 | struct conf_itrim_settings itrim; |
792 | struct conf_pm_config_settings pm_config; | 1027 | struct conf_pm_config_settings pm_config; |
1028 | struct conf_roam_trigger_settings roam_trigger; | ||
793 | }; | 1029 | }; |
794 | 1030 | ||
795 | #endif | 1031 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index 3f7ff8d0cf5a..c239ef4d0b8d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "wl1271.h" | 29 | #include "wl1271.h" |
30 | #include "wl1271_acx.h" | 30 | #include "wl1271_acx.h" |
31 | #include "wl1271_ps.h" | 31 | #include "wl1271_ps.h" |
32 | #include "wl1271_io.h" | ||
32 | 33 | ||
33 | /* ms */ | 34 | /* ms */ |
34 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 35 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
@@ -277,13 +278,10 @@ static ssize_t gpio_power_write(struct file *file, | |||
277 | goto out; | 278 | goto out; |
278 | } | 279 | } |
279 | 280 | ||
280 | if (value) { | 281 | if (value) |
281 | wl->set_power(true); | 282 | wl1271_power_on(wl); |
282 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 283 | else |
283 | } else { | 284 | wl1271_power_off(wl); |
284 | wl->set_power(false); | ||
285 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
286 | } | ||
287 | 285 | ||
288 | out: | 286 | out: |
289 | mutex_unlock(&wl->mutex); | 287 | mutex_unlock(&wl->mutex); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 7468ef10194b..cf37aa6eb137 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include "wl1271.h" | 24 | #include "wl1271.h" |
25 | #include "wl1271_reg.h" | 25 | #include "wl1271_reg.h" |
26 | #include "wl1271_spi.h" | ||
27 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
28 | #include "wl1271_event.h" | 27 | #include "wl1271_event.h" |
29 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
@@ -32,34 +31,24 @@ | |||
32 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 31 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
33 | struct event_mailbox *mbox) | 32 | struct event_mailbox *mbox) |
34 | { | 33 | { |
35 | int size = sizeof(struct wl12xx_probe_req_template); | ||
36 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 34 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
37 | mbox->scheduled_scan_status); | 35 | mbox->scheduled_scan_status); |
38 | 36 | ||
39 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 37 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
40 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 38 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
41 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
42 | NULL, size); | ||
43 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | 39 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend |
44 | * to the wl1271_cmd_scan function that we are not | 40 | * to the wl1271_cmd_scan function that we are not |
45 | * scanning as it checks that. | 41 | * scanning as it checks that. |
46 | */ | 42 | */ |
47 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 43 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
44 | /* FIXME: ie missing! */ | ||
48 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 45 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
46 | NULL, 0, | ||
49 | wl->scan.active, | 47 | wl->scan.active, |
50 | wl->scan.high_prio, | 48 | wl->scan.high_prio, |
51 | WL1271_SCAN_BAND_5_GHZ, | 49 | WL1271_SCAN_BAND_5_GHZ, |
52 | wl->scan.probe_requests); | 50 | wl->scan.probe_requests); |
53 | } else { | 51 | } else { |
54 | if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) | ||
55 | wl1271_cmd_template_set(wl, | ||
56 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
57 | NULL, size); | ||
58 | else | ||
59 | wl1271_cmd_template_set(wl, | ||
60 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
61 | NULL, size); | ||
62 | |||
63 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
64 | ieee80211_scan_completed(wl->hw, false); | 53 | ieee80211_scan_completed(wl->hw, false); |
65 | mutex_lock(&wl->mutex); | 54 | mutex_lock(&wl->mutex); |
@@ -92,16 +81,9 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
92 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 81 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
93 | true); | 82 | true); |
94 | } else { | 83 | } else { |
95 | wl1271_error("PSM entry failed, giving up.\n"); | 84 | wl1271_info("No ack to nullfunc from AP."); |
96 | /* FIXME: this may need to be reconsidered. for now it | ||
97 | is not possible to indicate to the mac80211 | ||
98 | afterwards that PSM entry failed. To maximize | ||
99 | functionality (receiving data and remaining | ||
100 | associated) make sure that we are in sync with the | ||
101 | AP in regard of PSM mode. */ | ||
102 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
103 | false); | ||
104 | wl->psm_entry_retry = 0; | 85 | wl->psm_entry_retry = 0; |
86 | *beacon_loss = true; | ||
105 | } | 87 | } |
106 | break; | 88 | break; |
107 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 89 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -143,6 +125,24 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
143 | return ret; | 125 | return ret; |
144 | } | 126 | } |
145 | 127 | ||
128 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | ||
129 | struct event_mailbox *mbox) | ||
130 | { | ||
131 | enum nl80211_cqm_rssi_threshold_event event; | ||
132 | s8 metric = mbox->rssi_snr_trigger_metric[0]; | ||
133 | |||
134 | wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); | ||
135 | |||
136 | if (metric <= wl->rssi_thold) | ||
137 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; | ||
138 | else | ||
139 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; | ||
140 | |||
141 | if (event != wl->last_rssi_event) | ||
142 | ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); | ||
143 | wl->last_rssi_event = event; | ||
144 | } | ||
145 | |||
146 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) | 146 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) |
147 | { | 147 | { |
148 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); | 148 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); |
@@ -172,10 +172,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
172 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 172 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon |
173 | * filtering) is enabled. Without PSM, the stack will receive all | 173 | * filtering) is enabled. Without PSM, the stack will receive all |
174 | * beacons and can detect beacon loss by itself. | 174 | * beacons and can detect beacon loss by itself. |
175 | * | ||
176 | * As there's possibility that the driver disables PSM before receiving | ||
177 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
178 | * | ||
175 | */ | 179 | */ |
176 | if (vector & BSS_LOSE_EVENT_ID && | 180 | if (vector & BSS_LOSE_EVENT_ID) { |
177 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 181 | wl1271_info("Beacon loss detected."); |
178 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | ||
179 | 182 | ||
180 | /* indicate to the stack, that beacons have been lost */ | 183 | /* indicate to the stack, that beacons have been lost */ |
181 | beacon_loss = true; | 184 | beacon_loss = true; |
@@ -188,17 +191,15 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
188 | return ret; | 191 | return ret; |
189 | } | 192 | } |
190 | 193 | ||
191 | if (wl->vif && beacon_loss) { | 194 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
192 | /* Obviously, it's dangerous to release the mutex while | 195 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
193 | we are holding many of the variables in the wl struct. | 196 | if (wl->vif) |
194 | That's why it's done last in the function, and care must | 197 | wl1271_event_rssi_trigger(wl, mbox); |
195 | be taken that nothing more is done after this function | ||
196 | returns. */ | ||
197 | mutex_unlock(&wl->mutex); | ||
198 | ieee80211_beacon_loss(wl->vif); | ||
199 | mutex_lock(&wl->mutex); | ||
200 | } | 198 | } |
201 | 199 | ||
200 | if (wl->vif && beacon_loss) | ||
201 | ieee80211_connection_loss(wl->vif); | ||
202 | |||
202 | return 0; | 203 | return 0; |
203 | } | 204 | } |
204 | 205 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 278f9206aa56..58371008f270 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -38,6 +38,14 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | RSSI_SNR_TRIGGER_0_EVENT_ID = BIT(0), | ||
42 | RSSI_SNR_TRIGGER_1_EVENT_ID = BIT(1), | ||
43 | RSSI_SNR_TRIGGER_2_EVENT_ID = BIT(2), | ||
44 | RSSI_SNR_TRIGGER_3_EVENT_ID = BIT(3), | ||
45 | RSSI_SNR_TRIGGER_4_EVENT_ID = BIT(4), | ||
46 | RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), | ||
47 | RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), | ||
48 | RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), | ||
41 | MEASUREMENT_START_EVENT_ID = BIT(8), | 49 | MEASUREMENT_START_EVENT_ID = BIT(8), |
42 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), | 50 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), |
43 | SCAN_COMPLETE_EVENT_ID = BIT(10), | 51 | SCAN_COMPLETE_EVENT_ID = BIT(10), |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index d189e8fe05a6..4447af1557f5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -52,50 +52,65 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
52 | 52 | ||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret; | 55 | int ret, i; |
56 | 56 | ||
57 | /* send empty templates for fw memory reservation */ | 57 | /* send empty templates for fw memory reservation */ |
58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
59 | sizeof(struct wl12xx_probe_req_template)); | 59 | sizeof(struct wl12xx_probe_req_template), |
60 | 0, WL1271_RATE_AUTOMATIC); | ||
60 | if (ret < 0) | 61 | if (ret < 0) |
61 | return ret; | 62 | return ret; |
62 | 63 | ||
63 | if (wl1271_11a_enabled()) { | 64 | if (wl1271_11a_enabled()) { |
65 | size_t size = sizeof(struct wl12xx_probe_req_template); | ||
64 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
65 | NULL, | 67 | NULL, size, 0, |
66 | sizeof(struct wl12xx_probe_req_template)); | 68 | WL1271_RATE_AUTOMATIC); |
67 | if (ret < 0) | 69 | if (ret < 0) |
68 | return ret; | 70 | return ret; |
69 | } | 71 | } |
70 | 72 | ||
71 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
72 | sizeof(struct wl12xx_null_data_template)); | 74 | sizeof(struct wl12xx_null_data_template), |
75 | 0, WL1271_RATE_AUTOMATIC); | ||
73 | if (ret < 0) | 76 | if (ret < 0) |
74 | return ret; | 77 | return ret; |
75 | 78 | ||
76 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, | 79 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, |
77 | sizeof(struct wl12xx_ps_poll_template)); | 80 | sizeof(struct wl12xx_ps_poll_template), |
81 | 0, WL1271_RATE_AUTOMATIC); | ||
78 | if (ret < 0) | 82 | if (ret < 0) |
79 | return ret; | 83 | return ret; |
80 | 84 | ||
81 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | 85 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, |
82 | sizeof | 86 | sizeof |
83 | (struct wl12xx_qos_null_data_template)); | 87 | (struct wl12xx_qos_null_data_template), |
88 | 0, WL1271_RATE_AUTOMATIC); | ||
84 | if (ret < 0) | 89 | if (ret < 0) |
85 | return ret; | 90 | return ret; |
86 | 91 | ||
87 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, | 92 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, |
88 | sizeof | 93 | sizeof |
89 | (struct wl12xx_probe_resp_template)); | 94 | (struct wl12xx_probe_resp_template), |
95 | 0, WL1271_RATE_AUTOMATIC); | ||
90 | if (ret < 0) | 96 | if (ret < 0) |
91 | return ret; | 97 | return ret; |
92 | 98 | ||
93 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, | 99 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, |
94 | sizeof | 100 | sizeof |
95 | (struct wl12xx_beacon_template)); | 101 | (struct wl12xx_beacon_template), |
102 | 0, WL1271_RATE_AUTOMATIC); | ||
96 | if (ret < 0) | 103 | if (ret < 0) |
97 | return ret; | 104 | return ret; |
98 | 105 | ||
106 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
107 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | ||
108 | WL1271_CMD_TEMPL_MAX_SIZE, i, | ||
109 | WL1271_RATE_AUTOMATIC); | ||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | } | ||
113 | |||
99 | return 0; | 114 | return 0; |
100 | } | 115 | } |
101 | 116 | ||
@@ -161,11 +176,11 @@ int wl1271_init_pta(struct wl1271 *wl) | |||
161 | { | 176 | { |
162 | int ret; | 177 | int ret; |
163 | 178 | ||
164 | ret = wl1271_acx_sg_enable(wl); | 179 | ret = wl1271_acx_sg_cfg(wl); |
165 | if (ret < 0) | 180 | if (ret < 0) |
166 | return ret; | 181 | return ret; |
167 | 182 | ||
168 | ret = wl1271_acx_sg_cfg(wl); | 183 | ret = wl1271_acx_sg_enable(wl, wl->sg_enabled); |
169 | if (ret < 0) | 184 | if (ret < 0) |
170 | return ret; | 185 | return ret; |
171 | 186 | ||
@@ -237,7 +252,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
237 | goto out_free_memmap; | 252 | goto out_free_memmap; |
238 | 253 | ||
239 | /* Initialize connection monitoring thresholds */ | 254 | /* Initialize connection monitoring thresholds */ |
240 | ret = wl1271_acx_conn_monit_params(wl); | 255 | ret = wl1271_acx_conn_monit_params(wl, false); |
241 | if (ret < 0) | 256 | if (ret < 0) |
242 | goto out_free_memmap; | 257 | goto out_free_memmap; |
243 | 258 | ||
@@ -325,6 +340,24 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
325 | if (ret < 0) | 340 | if (ret < 0) |
326 | goto out_free_memmap; | 341 | goto out_free_memmap; |
327 | 342 | ||
343 | /* disable all keep-alive templates */ | ||
344 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
345 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
346 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
347 | if (ret < 0) | ||
348 | goto out_free_memmap; | ||
349 | } | ||
350 | |||
351 | /* disable the keep-alive feature */ | ||
352 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
353 | if (ret < 0) | ||
354 | goto out_free_memmap; | ||
355 | |||
356 | /* Configure rssi/snr averaging weights */ | ||
357 | ret = wl1271_acx_rssi_snr_avg_weights(wl); | ||
358 | if (ret < 0) | ||
359 | goto out_free_memmap; | ||
360 | |||
328 | return 0; | 361 | return 0; |
329 | 362 | ||
330 | out_free_memmap: | 363 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index 5cd94d5666c2..c8759acef131 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c | |||
@@ -28,30 +28,29 @@ | |||
28 | 28 | ||
29 | #include "wl1271.h" | 29 | #include "wl1271.h" |
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | ||
32 | #include "wl1271_io.h" | 31 | #include "wl1271_io.h" |
33 | 32 | ||
34 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | 33 | #define OCP_CMD_LOOP 32 |
34 | |||
35 | #define OCP_CMD_WRITE 0x1 | ||
36 | #define OCP_CMD_READ 0x2 | ||
37 | |||
38 | #define OCP_READY_MASK BIT(18) | ||
39 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
40 | |||
41 | #define OCP_STATUS_NO_RESP 0x00000 | ||
42 | #define OCP_STATUS_OK 0x10000 | ||
43 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
44 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
45 | |||
46 | void wl1271_disable_interrupts(struct wl1271 *wl) | ||
35 | { | 47 | { |
36 | /* | 48 | wl->if_ops->disable_irq(wl); |
37 | * To translate, first check to which window of addresses the | 49 | } |
38 | * particular address belongs. Then subtract the starting address | 50 | |
39 | * of that window from the address. Then, add offset of the | 51 | void wl1271_enable_interrupts(struct wl1271 *wl) |
40 | * translated region. | 52 | { |
41 | * | 53 | wl->if_ops->enable_irq(wl); |
42 | * The translated regions occur next to each other in physical device | ||
43 | * memory, so just add the sizes of the preceeding address regions to | ||
44 | * get the offset to the new region. | ||
45 | * | ||
46 | * Currently, only the two first regions are addressed, and the | ||
47 | * assumption is that all addresses will fall into either of those | ||
48 | * two. | ||
49 | */ | ||
50 | if ((addr >= wl->part.reg.start) && | ||
51 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
52 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
53 | else | ||
54 | return addr - wl->part.mem.start; | ||
55 | } | 54 | } |
56 | 55 | ||
57 | /* Set the SPI partitions to access the chip addresses | 56 | /* Set the SPI partitions to access the chip addresses |
@@ -117,54 +116,12 @@ int wl1271_set_partition(struct wl1271 *wl, | |||
117 | 116 | ||
118 | void wl1271_io_reset(struct wl1271 *wl) | 117 | void wl1271_io_reset(struct wl1271 *wl) |
119 | { | 118 | { |
120 | wl1271_spi_reset(wl); | 119 | wl->if_ops->reset(wl); |
121 | } | 120 | } |
122 | 121 | ||
123 | void wl1271_io_init(struct wl1271 *wl) | 122 | void wl1271_io_init(struct wl1271 *wl) |
124 | { | 123 | { |
125 | wl1271_spi_init(wl); | 124 | wl->if_ops->init(wl); |
126 | } | ||
127 | |||
128 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
129 | size_t len, bool fixed) | ||
130 | { | ||
131 | wl1271_spi_raw_write(wl, addr, buf, len, fixed); | ||
132 | } | ||
133 | |||
134 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
135 | size_t len, bool fixed) | ||
136 | { | ||
137 | wl1271_spi_raw_read(wl, addr, buf, len, fixed); | ||
138 | } | ||
139 | |||
140 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
141 | bool fixed) | ||
142 | { | ||
143 | int physical; | ||
144 | |||
145 | physical = wl1271_translate_addr(wl, addr); | ||
146 | |||
147 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
148 | } | ||
149 | |||
150 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
151 | bool fixed) | ||
152 | { | ||
153 | int physical; | ||
154 | |||
155 | physical = wl1271_translate_addr(wl, addr); | ||
156 | |||
157 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
158 | } | ||
159 | |||
160 | u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
161 | { | ||
162 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
163 | } | ||
164 | |||
165 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
166 | { | ||
167 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
168 | } | 125 | } |
169 | 126 | ||
170 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 127 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index fa9a0b35788f..bc806c74c63a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -25,44 +25,145 @@ | |||
25 | #ifndef __WL1271_IO_H__ | 25 | #ifndef __WL1271_IO_H__ |
26 | #define __WL1271_IO_H__ | 26 | #define __WL1271_IO_H__ |
27 | 27 | ||
28 | #include "wl1271_reg.h" | ||
29 | |||
30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | ||
31 | |||
32 | #define HW_PARTITION_REGISTERS_ADDR 0x1FFC0 | ||
33 | #define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) | ||
34 | #define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) | ||
35 | #define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) | ||
36 | #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) | ||
37 | #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) | ||
38 | #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) | ||
39 | #define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) | ||
40 | |||
41 | #define HW_ACCESS_REGISTER_SIZE 4 | ||
42 | |||
43 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | ||
44 | |||
28 | struct wl1271; | 45 | struct wl1271; |
29 | 46 | ||
47 | void wl1271_disable_interrupts(struct wl1271 *wl); | ||
48 | void wl1271_enable_interrupts(struct wl1271 *wl); | ||
49 | |||
30 | void wl1271_io_reset(struct wl1271 *wl); | 50 | void wl1271_io_reset(struct wl1271 *wl); |
31 | void wl1271_io_init(struct wl1271 *wl); | 51 | void wl1271_io_init(struct wl1271 *wl); |
32 | 52 | ||
33 | /* Raw target IO, address is not translated */ | 53 | static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl) |
34 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 54 | { |
35 | size_t len, bool fixed); | 55 | return wl->if_ops->dev(wl); |
36 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | 56 | } |
37 | size_t len, bool fixed); | ||
38 | 57 | ||
39 | /* Translated target IO */ | ||
40 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
41 | bool fixed); | ||
42 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
43 | bool fixed); | ||
44 | u32 wl1271_read32(struct wl1271 *wl, int addr); | ||
45 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val); | ||
46 | 58 | ||
47 | /* Top Register IO */ | 59 | /* Raw target IO, address is not translated */ |
48 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | 60 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, |
49 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | 61 | size_t len, bool fixed) |
62 | { | ||
63 | wl->if_ops->write(wl, addr, buf, len, fixed); | ||
64 | } | ||
50 | 65 | ||
51 | int wl1271_set_partition(struct wl1271 *wl, | 66 | static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, |
52 | struct wl1271_partition_set *p); | 67 | size_t len, bool fixed) |
68 | { | ||
69 | wl->if_ops->read(wl, addr, buf, len, fixed); | ||
70 | } | ||
53 | 71 | ||
54 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 72 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) |
55 | { | 73 | { |
56 | wl1271_raw_read(wl, addr, &wl->buffer_32, | 74 | wl1271_raw_read(wl, addr, &wl->buffer_32, |
57 | sizeof(wl->buffer_32), false); | 75 | sizeof(wl->buffer_32), false); |
58 | 76 | ||
59 | return wl->buffer_32; | 77 | return le32_to_cpu(wl->buffer_32); |
60 | } | 78 | } |
61 | 79 | ||
62 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | 80 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) |
63 | { | 81 | { |
64 | wl->buffer_32 = val; | 82 | wl->buffer_32 = cpu_to_le32(val); |
65 | wl1271_raw_write(wl, addr, &wl->buffer_32, | 83 | wl1271_raw_write(wl, addr, &wl->buffer_32, |
66 | sizeof(wl->buffer_32), false); | 84 | sizeof(wl->buffer_32), false); |
67 | } | 85 | } |
86 | |||
87 | /* Translated target IO */ | ||
88 | static inline int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
89 | { | ||
90 | /* | ||
91 | * To translate, first check to which window of addresses the | ||
92 | * particular address belongs. Then subtract the starting address | ||
93 | * of that window from the address. Then, add offset of the | ||
94 | * translated region. | ||
95 | * | ||
96 | * The translated regions occur next to each other in physical device | ||
97 | * memory, so just add the sizes of the preceeding address regions to | ||
98 | * get the offset to the new region. | ||
99 | * | ||
100 | * Currently, only the two first regions are addressed, and the | ||
101 | * assumption is that all addresses will fall into either of those | ||
102 | * two. | ||
103 | */ | ||
104 | if ((addr >= wl->part.reg.start) && | ||
105 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
106 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
107 | else | ||
108 | return addr - wl->part.mem.start; | ||
109 | } | ||
110 | |||
111 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | ||
112 | size_t len, bool fixed) | ||
113 | { | ||
114 | int physical; | ||
115 | |||
116 | physical = wl1271_translate_addr(wl, addr); | ||
117 | |||
118 | wl1271_raw_read(wl, physical, buf, len, fixed); | ||
119 | } | ||
120 | |||
121 | static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | ||
122 | size_t len, bool fixed) | ||
123 | { | ||
124 | int physical; | ||
125 | |||
126 | physical = wl1271_translate_addr(wl, addr); | ||
127 | |||
128 | wl1271_raw_write(wl, physical, buf, len, fixed); | ||
129 | } | ||
130 | |||
131 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
132 | { | ||
133 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
134 | } | ||
135 | |||
136 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
137 | { | ||
138 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
139 | } | ||
140 | |||
141 | static inline void wl1271_power_off(struct wl1271 *wl) | ||
142 | { | ||
143 | wl->if_ops->power(wl, false); | ||
144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
145 | } | ||
146 | |||
147 | static inline void wl1271_power_on(struct wl1271 *wl) | ||
148 | { | ||
149 | wl->if_ops->power(wl, true); | ||
150 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
151 | } | ||
152 | |||
153 | |||
154 | /* Top Register IO */ | ||
155 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
156 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
157 | |||
158 | int wl1271_set_partition(struct wl1271 *wl, | ||
159 | struct wl1271_partition_set *p); | ||
160 | |||
161 | /* Functions from wl1271_main.c */ | ||
162 | |||
163 | int wl1271_register_hw(struct wl1271 *wl); | ||
164 | void wl1271_unregister_hw(struct wl1271 *wl); | ||
165 | int wl1271_init_ieee80211(struct wl1271 *wl); | ||
166 | struct ieee80211_hw *wl1271_alloc_hw(void); | ||
167 | int wl1271_free_hw(struct wl1271 *wl); | ||
168 | |||
68 | #endif | 169 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 65a1aeba2419..b7d9137851ac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -22,23 +22,19 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
28 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
29 | #include <linux/irq.h> | ||
30 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
31 | #include <linux/crc32.h> | 28 | #include <linux/crc32.h> |
32 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
33 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
34 | #include <linux/spi/wl12xx.h> | ||
35 | #include <linux/inetdevice.h> | 31 | #include <linux/inetdevice.h> |
32 | #include <linux/platform_device.h> | ||
36 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
37 | 34 | ||
38 | #include "wl1271.h" | 35 | #include "wl1271.h" |
39 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
40 | #include "wl1271_reg.h" | 37 | #include "wl1271_reg.h" |
41 | #include "wl1271_spi.h" | ||
42 | #include "wl1271_io.h" | 38 | #include "wl1271_io.h" |
43 | #include "wl1271_event.h" | 39 | #include "wl1271_event.h" |
44 | #include "wl1271_tx.h" | 40 | #include "wl1271_tx.h" |
@@ -54,17 +50,57 @@ | |||
54 | 50 | ||
55 | static struct conf_drv_settings default_conf = { | 51 | static struct conf_drv_settings default_conf = { |
56 | .sg = { | 52 | .sg = { |
57 | .per_threshold = 7500, | 53 | .params = { |
58 | .max_scan_compensation_time = 120000, | 54 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
59 | .nfs_sample_interval = 400, | 55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
60 | .load_ratio = 50, | 56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
61 | .auto_ps_mode = 0, | 57 | [CONF_SG_BT_LOAD_RATIO] = 50, |
62 | .probe_req_compensation = 170, | 58 | [CONF_SG_AUTO_PS_MODE] = 0, |
63 | .scan_window_compensation = 50, | 59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
64 | .antenna_config = 0, | 60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
65 | .beacon_miss_threshold = 60, | 61 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, |
66 | .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, | 62 | [CONF_SG_BEACON_MISS_PERCENT] = 60, |
67 | .rate_adaptation_snr = 0 | 63 | [CONF_SG_RATE_ADAPT_THRESH] = 12, |
64 | [CONF_SG_RATE_ADAPT_SNR] = 0, | ||
65 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
66 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, | ||
67 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, | ||
68 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
69 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, | ||
70 | /* Note: with UPSD, this should be 4 */ | ||
71 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, | ||
72 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
73 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
74 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, | ||
75 | /* Note: with UPDS, this should be 15 */ | ||
76 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
77 | /* Note: with UPDS, this should be 50 */ | ||
78 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, | ||
79 | /* Note: with UPDS, this should be 10 */ | ||
80 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, | ||
81 | [CONF_SG_RXT] = 1200, | ||
82 | [CONF_SG_TXT] = 1000, | ||
83 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
84 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
85 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
86 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
87 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
88 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
89 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
90 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
91 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
92 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
93 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
94 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
95 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
96 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
97 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
98 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
99 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
100 | [CONF_SG_DHCP_TIME] = 5000, | ||
101 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
102 | }, | ||
103 | .state = CONF_SG_PROTECTIVE, | ||
68 | }, | 104 | }, |
69 | .rx = { | 105 | .rx = { |
70 | .rx_msdu_life_time = 512000, | 106 | .rx_msdu_life_time = 512000, |
@@ -81,8 +117,7 @@ static struct conf_drv_settings default_conf = { | |||
81 | .tx = { | 117 | .tx = { |
82 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
83 | .rc_conf = { | 119 | .rc_conf = { |
84 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 120 | .enabled_rates = 0, |
85 | CONF_HW_BIT_RATE_2MBPS, | ||
86 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
87 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
88 | .aflags = 0 | 123 | .aflags = 0 |
@@ -179,11 +214,13 @@ static struct conf_drv_settings default_conf = { | |||
179 | }, | 214 | }, |
180 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
181 | .tx_compl_timeout = 700, | 216 | .tx_compl_timeout = 700, |
182 | .tx_compl_threshold = 4 | 217 | .tx_compl_threshold = 4, |
218 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
219 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
183 | }, | 220 | }, |
184 | .conn = { | 221 | .conn = { |
185 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
186 | .listen_interval = 0, | 223 | .listen_interval = 1, |
187 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 224 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
188 | .bcn_filt_ie_count = 1, | 225 | .bcn_filt_ie_count = 1, |
189 | .bcn_filt_ie = { | 226 | .bcn_filt_ie = { |
@@ -198,38 +235,11 @@ static struct conf_drv_settings default_conf = { | |||
198 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
199 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
200 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 20, |
201 | .sig_trigger_count = 2, | ||
202 | .sig_trigger = { | ||
203 | [0] = { | ||
204 | .threshold = -75, | ||
205 | .pacing = 500, | ||
206 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
207 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
208 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
209 | .hysteresis = 2, | ||
210 | .index = 0, | ||
211 | .enable = 1 | ||
212 | }, | ||
213 | [1] = { | ||
214 | .threshold = -75, | ||
215 | .pacing = 500, | ||
216 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
217 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
218 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
219 | .hysteresis = 2, | ||
220 | .index = 1, | ||
221 | .enable = 1 | ||
222 | } | ||
223 | }, | ||
224 | .sig_weights = { | ||
225 | .rssi_bcn_avg_weight = 10, | ||
226 | .rssi_pkt_avg_weight = 10, | ||
227 | .snr_bcn_avg_weight = 10, | ||
228 | .snr_pkt_avg_weight = 10 | ||
229 | }, | ||
230 | .bet_enable = CONF_BET_MODE_ENABLE, | 238 | .bet_enable = CONF_BET_MODE_ENABLE, |
231 | .bet_max_consecutive = 10, | 239 | .bet_max_consecutive = 10, |
232 | .psm_entry_retries = 3 | 240 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | ||
242 | .max_listen_interval = 20, | ||
233 | }, | 243 | }, |
234 | .init = { | 244 | .init = { |
235 | .radioparam = { | 245 | .radioparam = { |
@@ -243,9 +253,32 @@ static struct conf_drv_settings default_conf = { | |||
243 | .pm_config = { | 253 | .pm_config = { |
244 | .host_clk_settling_time = 5000, | 254 | .host_clk_settling_time = 5000, |
245 | .host_fast_wakeup_support = false | 255 | .host_fast_wakeup_support = false |
256 | }, | ||
257 | .roam_trigger = { | ||
258 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
259 | .trigger_pacing = 1, | ||
260 | .avg_weight_rssi_beacon = 20, | ||
261 | .avg_weight_rssi_data = 10, | ||
262 | .avg_weight_snr_beacon = 20, | ||
263 | .avg_weight_snr_data = 10 | ||
246 | } | 264 | } |
247 | }; | 265 | }; |
248 | 266 | ||
267 | static void wl1271_device_release(struct device *dev) | ||
268 | { | ||
269 | |||
270 | } | ||
271 | |||
272 | static struct platform_device wl1271_device = { | ||
273 | .name = "wl1271", | ||
274 | .id = -1, | ||
275 | |||
276 | /* device model insists to have a release function */ | ||
277 | .dev = { | ||
278 | .release = wl1271_device_release, | ||
279 | }, | ||
280 | }; | ||
281 | |||
249 | static LIST_HEAD(wl_list); | 282 | static LIST_HEAD(wl_list); |
250 | 283 | ||
251 | static void wl1271_conf_init(struct wl1271 *wl) | 284 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -298,7 +331,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
298 | goto out_free_memmap; | 331 | goto out_free_memmap; |
299 | 332 | ||
300 | /* Initialize connection monitoring thresholds */ | 333 | /* Initialize connection monitoring thresholds */ |
301 | ret = wl1271_acx_conn_monit_params(wl); | 334 | ret = wl1271_acx_conn_monit_params(wl, false); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out_free_memmap; | 336 | goto out_free_memmap; |
304 | 337 | ||
@@ -365,30 +398,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
365 | return ret; | 398 | return ret; |
366 | } | 399 | } |
367 | 400 | ||
368 | static void wl1271_disable_interrupts(struct wl1271 *wl) | ||
369 | { | ||
370 | disable_irq(wl->irq); | ||
371 | } | ||
372 | |||
373 | static void wl1271_power_off(struct wl1271 *wl) | ||
374 | { | ||
375 | wl->set_power(false); | ||
376 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | ||
378 | |||
379 | static void wl1271_power_on(struct wl1271 *wl) | ||
380 | { | ||
381 | wl->set_power(true); | ||
382 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
383 | } | ||
384 | |||
385 | static void wl1271_fw_status(struct wl1271 *wl, | 401 | static void wl1271_fw_status(struct wl1271 *wl, |
386 | struct wl1271_fw_status *status) | 402 | struct wl1271_fw_status *status) |
387 | { | 403 | { |
404 | struct timespec ts; | ||
388 | u32 total = 0; | 405 | u32 total = 0; |
389 | int i; | 406 | int i; |
390 | 407 | ||
391 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 408 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
392 | 409 | ||
393 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 410 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
394 | "drv_rx_counter = %d, tx_results_counter = %d)", | 411 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -413,14 +430,19 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
413 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 430 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
414 | 431 | ||
415 | /* update the host-chipset time offset */ | 432 | /* update the host-chipset time offset */ |
416 | wl->time_offset = jiffies_to_usecs(jiffies) - | 433 | getnstimeofday(&ts); |
417 | le32_to_cpu(status->fw_localtime); | 434 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
435 | (s64)le32_to_cpu(status->fw_localtime); | ||
418 | } | 436 | } |
419 | 437 | ||
438 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
439 | |||
420 | static void wl1271_irq_work(struct work_struct *work) | 440 | static void wl1271_irq_work(struct work_struct *work) |
421 | { | 441 | { |
422 | int ret; | 442 | int ret; |
423 | u32 intr; | 443 | u32 intr; |
444 | int loopcount = WL1271_IRQ_MAX_LOOPS; | ||
445 | unsigned long flags; | ||
424 | struct wl1271 *wl = | 446 | struct wl1271 *wl = |
425 | container_of(work, struct wl1271, irq_work); | 447 | container_of(work, struct wl1271, irq_work); |
426 | 448 | ||
@@ -428,91 +450,78 @@ static void wl1271_irq_work(struct work_struct *work) | |||
428 | 450 | ||
429 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 451 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
430 | 452 | ||
431 | if (wl->state == WL1271_STATE_OFF) | 453 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
432 | goto out; | 454 | goto out; |
433 | 455 | ||
434 | ret = wl1271_ps_elp_wakeup(wl, true); | 456 | ret = wl1271_ps_elp_wakeup(wl, true); |
435 | if (ret < 0) | 457 | if (ret < 0) |
436 | goto out; | 458 | goto out; |
437 | 459 | ||
438 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 460 | spin_lock_irqsave(&wl->wl_lock, flags); |
439 | 461 | while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { | |
440 | wl1271_fw_status(wl, wl->fw_status); | 462 | clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); |
441 | intr = le32_to_cpu(wl->fw_status->intr); | 463 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
442 | if (!intr) { | 464 | loopcount--; |
443 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 465 | |
444 | goto out_sleep; | 466 | wl1271_fw_status(wl, wl->fw_status); |
445 | } | 467 | intr = le32_to_cpu(wl->fw_status->intr); |
468 | if (!intr) { | ||
469 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | ||
470 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
471 | continue; | ||
472 | } | ||
446 | 473 | ||
447 | intr &= WL1271_INTR_MASK; | 474 | intr &= WL1271_INTR_MASK; |
448 | 475 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 476 | if (intr & WL1271_ACX_INTR_DATA) { |
450 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 477 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
451 | wl1271_event_handle(wl, 0); | ||
452 | } | ||
453 | 478 | ||
454 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 479 | /* check for tx results */ |
455 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 480 | if (wl->fw_status->tx_results_counter != |
456 | wl1271_event_handle(wl, 1); | 481 | (wl->tx_results_count & 0xff)) |
457 | } | 482 | wl1271_tx_complete(wl); |
458 | 483 | ||
459 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 484 | wl1271_rx(wl, wl->fw_status); |
460 | wl1271_debug(DEBUG_IRQ, | 485 | } |
461 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
462 | 486 | ||
463 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 487 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
464 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 488 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
489 | wl1271_event_handle(wl, 0); | ||
490 | } | ||
465 | 491 | ||
466 | if (intr & WL1271_ACX_INTR_DATA) { | 492 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
467 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 493 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
468 | wl->tx_results_count; | 494 | wl1271_event_handle(wl, 1); |
495 | } | ||
469 | 496 | ||
470 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 497 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
498 | wl1271_debug(DEBUG_IRQ, | ||
499 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
471 | 500 | ||
472 | /* check for tx results */ | 501 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
473 | if (tx_res_cnt) | 502 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
474 | wl1271_tx_complete(wl, tx_res_cnt); | ||
475 | 503 | ||
476 | wl1271_rx(wl, wl->fw_status); | 504 | spin_lock_irqsave(&wl->wl_lock, flags); |
477 | } | 505 | } |
478 | 506 | ||
479 | out_sleep: | 507 | if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) |
480 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 508 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
481 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 509 | else |
510 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
511 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
512 | |||
482 | wl1271_ps_elp_sleep(wl); | 513 | wl1271_ps_elp_sleep(wl); |
483 | 514 | ||
484 | out: | 515 | out: |
485 | mutex_unlock(&wl->mutex); | 516 | mutex_unlock(&wl->mutex); |
486 | } | 517 | } |
487 | 518 | ||
488 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
489 | { | ||
490 | struct wl1271 *wl; | ||
491 | unsigned long flags; | ||
492 | |||
493 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
494 | |||
495 | wl = cookie; | ||
496 | |||
497 | /* complete the ELP completion */ | ||
498 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
499 | if (wl->elp_compl) { | ||
500 | complete(wl->elp_compl); | ||
501 | wl->elp_compl = NULL; | ||
502 | } | ||
503 | |||
504 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
505 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
506 | |||
507 | return IRQ_HANDLED; | ||
508 | } | ||
509 | |||
510 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 519 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
511 | { | 520 | { |
512 | const struct firmware *fw; | 521 | const struct firmware *fw; |
513 | int ret; | 522 | int ret; |
514 | 523 | ||
515 | ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); | 524 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); |
516 | 525 | ||
517 | if (ret < 0) { | 526 | if (ret < 0) { |
518 | wl1271_error("could not get firmware: %d", ret); | 527 | wl1271_error("could not get firmware: %d", ret); |
@@ -545,46 +554,12 @@ out: | |||
545 | return ret; | 554 | return ret; |
546 | } | 555 | } |
547 | 556 | ||
548 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
549 | { | ||
550 | int ret = 0; | ||
551 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
552 | |||
553 | /* get mac address from the NVS */ | ||
554 | wl->mac_addr[0] = nvs_ptr[11]; | ||
555 | wl->mac_addr[1] = nvs_ptr[10]; | ||
556 | wl->mac_addr[2] = nvs_ptr[6]; | ||
557 | wl->mac_addr[3] = nvs_ptr[5]; | ||
558 | wl->mac_addr[4] = nvs_ptr[4]; | ||
559 | wl->mac_addr[5] = nvs_ptr[3]; | ||
560 | |||
561 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
562 | we randomize an address */ | ||
563 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
564 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
565 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
566 | get_random_bytes(wl->mac_addr + 3, 3); | ||
567 | |||
568 | /* update this address to the NVS */ | ||
569 | nvs_ptr[11] = wl->mac_addr[0]; | ||
570 | nvs_ptr[10] = wl->mac_addr[1]; | ||
571 | nvs_ptr[6] = wl->mac_addr[2]; | ||
572 | nvs_ptr[5] = wl->mac_addr[3]; | ||
573 | nvs_ptr[4] = wl->mac_addr[4]; | ||
574 | nvs_ptr[3] = wl->mac_addr[5]; | ||
575 | } | ||
576 | |||
577 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
578 | |||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 557 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
583 | { | 558 | { |
584 | const struct firmware *fw; | 559 | const struct firmware *fw; |
585 | int ret; | 560 | int ret; |
586 | 561 | ||
587 | ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); | 562 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); |
588 | 563 | ||
589 | if (ret < 0) { | 564 | if (ret < 0) { |
590 | wl1271_error("could not get nvs file: %d", ret); | 565 | wl1271_error("could not get nvs file: %d", ret); |
@@ -608,8 +583,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
608 | 583 | ||
609 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); | 584 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
610 | 585 | ||
611 | ret = wl1271_update_mac_addr(wl); | ||
612 | |||
613 | out: | 586 | out: |
614 | release_firmware(fw); | 587 | release_firmware(fw); |
615 | 588 | ||
@@ -826,15 +799,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
826 | * The workqueue is slow to process the tx_queue and we need stop | 799 | * The workqueue is slow to process the tx_queue and we need stop |
827 | * the queue here, otherwise the queue will get too long. | 800 | * the queue here, otherwise the queue will get too long. |
828 | */ | 801 | */ |
829 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { | 802 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
830 | ieee80211_stop_queues(wl->hw); | 803 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
831 | 804 | ||
832 | /* | 805 | spin_lock_irqsave(&wl->wl_lock, flags); |
833 | * FIXME: this is racy, the variable is not properly | 806 | ieee80211_stop_queues(wl->hw); |
834 | * protected. Maybe fix this by removing the stupid | ||
835 | * variable altogether and checking the real queue state? | ||
836 | */ | ||
837 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 807 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
808 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
838 | } | 809 | } |
839 | 810 | ||
840 | return NETDEV_TX_OK; | 811 | return NETDEV_TX_OK; |
@@ -882,7 +853,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
882 | if (wl == wl_temp) | 853 | if (wl == wl_temp) |
883 | break; | 854 | break; |
884 | } | 855 | } |
885 | if (wl == NULL) | 856 | if (wl != wl_temp) |
886 | return NOTIFY_DONE; | 857 | return NOTIFY_DONE; |
887 | 858 | ||
888 | /* Get the interface IP address for the device. "ifa" will become | 859 | /* Get the interface IP address for the device. "ifa" will become |
@@ -929,13 +900,60 @@ static struct notifier_block wl1271_dev_notifier = { | |||
929 | 900 | ||
930 | static int wl1271_op_start(struct ieee80211_hw *hw) | 901 | static int wl1271_op_start(struct ieee80211_hw *hw) |
931 | { | 902 | { |
903 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | ||
904 | |||
905 | /* | ||
906 | * We have to delay the booting of the hardware because | ||
907 | * we need to know the local MAC address before downloading and | ||
908 | * initializing the firmware. The MAC address cannot be changed | ||
909 | * after boot, and without the proper MAC address, the firmware | ||
910 | * will not function properly. | ||
911 | * | ||
912 | * The MAC address is first known when the corresponding interface | ||
913 | * is added. That is where we will initialize the hardware. | ||
914 | */ | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static void wl1271_op_stop(struct ieee80211_hw *hw) | ||
920 | { | ||
921 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
922 | } | ||
923 | |||
924 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | ||
925 | struct ieee80211_vif *vif) | ||
926 | { | ||
932 | struct wl1271 *wl = hw->priv; | 927 | struct wl1271 *wl = hw->priv; |
933 | int retries = WL1271_BOOT_RETRIES; | 928 | int retries = WL1271_BOOT_RETRIES; |
934 | int ret = 0; | 929 | int ret = 0; |
935 | 930 | ||
936 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 931 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
932 | vif->type, vif->addr); | ||
937 | 933 | ||
938 | mutex_lock(&wl->mutex); | 934 | mutex_lock(&wl->mutex); |
935 | if (wl->vif) { | ||
936 | ret = -EBUSY; | ||
937 | goto out; | ||
938 | } | ||
939 | |||
940 | wl->vif = vif; | ||
941 | |||
942 | switch (vif->type) { | ||
943 | case NL80211_IFTYPE_STATION: | ||
944 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
945 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
946 | break; | ||
947 | case NL80211_IFTYPE_ADHOC: | ||
948 | wl->bss_type = BSS_TYPE_IBSS; | ||
949 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
950 | break; | ||
951 | default: | ||
952 | ret = -EOPNOTSUPP; | ||
953 | goto out; | ||
954 | } | ||
955 | |||
956 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
939 | 957 | ||
940 | if (wl->state != WL1271_STATE_OFF) { | 958 | if (wl->state != WL1271_STATE_OFF) { |
941 | wl1271_error("cannot start because not in off state: %d", | 959 | wl1271_error("cannot start because not in off state: %d", |
@@ -991,19 +1009,20 @@ out: | |||
991 | return ret; | 1009 | return ret; |
992 | } | 1010 | } |
993 | 1011 | ||
994 | static void wl1271_op_stop(struct ieee80211_hw *hw) | 1012 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1013 | struct ieee80211_vif *vif) | ||
995 | { | 1014 | { |
996 | struct wl1271 *wl = hw->priv; | 1015 | struct wl1271 *wl = hw->priv; |
997 | int i; | 1016 | int i; |
998 | 1017 | ||
999 | wl1271_info("down"); | ||
1000 | |||
1001 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
1002 | |||
1003 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | 1018 | unregister_inetaddr_notifier(&wl1271_dev_notifier); |
1004 | list_del(&wl->list); | ||
1005 | 1019 | ||
1006 | mutex_lock(&wl->mutex); | 1020 | mutex_lock(&wl->mutex); |
1021 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1022 | |||
1023 | wl1271_info("down"); | ||
1024 | |||
1025 | list_del(&wl->list); | ||
1007 | 1026 | ||
1008 | WARN_ON(wl->state != WL1271_STATE_ON); | 1027 | WARN_ON(wl->state != WL1271_STATE_ON); |
1009 | 1028 | ||
@@ -1032,6 +1051,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1032 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1051 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1033 | wl->ssid_len = 0; | 1052 | wl->ssid_len = 0; |
1034 | wl->bss_type = MAX_BSS_TYPE; | 1053 | wl->bss_type = MAX_BSS_TYPE; |
1054 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1035 | wl->band = IEEE80211_BAND_2GHZ; | 1055 | wl->band = IEEE80211_BAND_2GHZ; |
1036 | 1056 | ||
1037 | wl->rx_counter = 0; | 1057 | wl->rx_counter = 0; |
@@ -1041,163 +1061,142 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1041 | wl->tx_results_count = 0; | 1061 | wl->tx_results_count = 0; |
1042 | wl->tx_packets_count = 0; | 1062 | wl->tx_packets_count = 0; |
1043 | wl->tx_security_last_seq = 0; | 1063 | wl->tx_security_last_seq = 0; |
1044 | wl->tx_security_seq_16 = 0; | 1064 | wl->tx_security_seq = 0; |
1045 | wl->tx_security_seq_32 = 0; | ||
1046 | wl->time_offset = 0; | 1065 | wl->time_offset = 0; |
1047 | wl->session_counter = 0; | 1066 | wl->session_counter = 0; |
1048 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1067 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1049 | wl->sta_rate_set = 0; | 1068 | wl->sta_rate_set = 0; |
1050 | wl->flags = 0; | 1069 | wl->flags = 0; |
1070 | wl->vif = NULL; | ||
1071 | wl->filters = 0; | ||
1051 | 1072 | ||
1052 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1073 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1053 | wl->tx_blocks_freed[i] = 0; | 1074 | wl->tx_blocks_freed[i] = 0; |
1054 | 1075 | ||
1055 | wl1271_debugfs_reset(wl); | 1076 | wl1271_debugfs_reset(wl); |
1077 | |||
1078 | kfree(wl->fw_status); | ||
1079 | wl->fw_status = NULL; | ||
1080 | kfree(wl->tx_res_if); | ||
1081 | wl->tx_res_if = NULL; | ||
1082 | kfree(wl->target_mem_map); | ||
1083 | wl->target_mem_map = NULL; | ||
1084 | |||
1056 | mutex_unlock(&wl->mutex); | 1085 | mutex_unlock(&wl->mutex); |
1057 | } | 1086 | } |
1058 | 1087 | ||
1059 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1088 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1060 | struct ieee80211_vif *vif) | ||
1061 | { | 1089 | { |
1062 | struct wl1271 *wl = hw->priv; | 1090 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1063 | int ret = 0; | 1091 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1064 | 1092 | ||
1065 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1093 | /* combine requested filters with current filter config */ |
1066 | vif->type, vif->addr); | 1094 | filters = wl->filters | filters; |
1067 | 1095 | ||
1068 | mutex_lock(&wl->mutex); | 1096 | wl1271_debug(DEBUG_FILTERS, "RX filters set: "); |
1069 | if (wl->vif) { | 1097 | |
1070 | ret = -EBUSY; | 1098 | if (filters & FIF_PROMISC_IN_BSS) { |
1071 | goto out; | 1099 | wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); |
1100 | wl->rx_config &= ~CFG_UNI_FILTER_EN; | ||
1101 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1102 | } | ||
1103 | if (filters & FIF_BCN_PRBRESP_PROMISC) { | ||
1104 | wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); | ||
1105 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1106 | wl->rx_config &= ~CFG_SSID_FILTER_EN; | ||
1072 | } | 1107 | } |
1108 | if (filters & FIF_OTHER_BSS) { | ||
1109 | wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); | ||
1110 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1111 | } | ||
1112 | if (filters & FIF_CONTROL) { | ||
1113 | wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); | ||
1114 | wl->rx_filter |= CFG_RX_CTL_EN; | ||
1115 | } | ||
1116 | if (filters & FIF_FCSFAIL) { | ||
1117 | wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); | ||
1118 | wl->rx_filter |= CFG_RX_FCS_ERROR; | ||
1119 | } | ||
1120 | } | ||
1073 | 1121 | ||
1074 | wl->vif = vif; | 1122 | static int wl1271_dummy_join(struct wl1271 *wl) |
1123 | { | ||
1124 | int ret = 0; | ||
1125 | /* we need to use a dummy BSSID for now */ | ||
1126 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1127 | 0xad, 0xbe, 0xef }; | ||
1075 | 1128 | ||
1076 | switch (vif->type) { | 1129 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1077 | case NL80211_IFTYPE_STATION: | 1130 | |
1078 | wl->bss_type = BSS_TYPE_STA_BSS; | 1131 | /* pass through frames from all BSS */ |
1079 | break; | 1132 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1080 | case NL80211_IFTYPE_ADHOC: | 1133 | |
1081 | wl->bss_type = BSS_TYPE_IBSS; | 1134 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1082 | break; | 1135 | if (ret < 0) |
1083 | default: | ||
1084 | ret = -EOPNOTSUPP; | ||
1085 | goto out; | 1136 | goto out; |
1086 | } | ||
1087 | 1137 | ||
1088 | /* FIXME: what if conf->mac_addr changes? */ | 1138 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1089 | 1139 | ||
1090 | out: | 1140 | out: |
1091 | mutex_unlock(&wl->mutex); | ||
1092 | return ret; | 1141 | return ret; |
1093 | } | 1142 | } |
1094 | 1143 | ||
1095 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1144 | static int wl1271_join(struct wl1271 *wl, bool set_assoc) |
1096 | struct ieee80211_vif *vif) | ||
1097 | { | ||
1098 | struct wl1271 *wl = hw->priv; | ||
1099 | |||
1100 | mutex_lock(&wl->mutex); | ||
1101 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1102 | wl->vif = NULL; | ||
1103 | mutex_unlock(&wl->mutex); | ||
1104 | } | ||
1105 | |||
1106 | #if 0 | ||
1107 | static int wl1271_op_config_interface(struct ieee80211_hw *hw, | ||
1108 | struct ieee80211_vif *vif, | ||
1109 | struct ieee80211_if_conf *conf) | ||
1110 | { | 1145 | { |
1111 | struct wl1271 *wl = hw->priv; | ||
1112 | struct sk_buff *beacon; | ||
1113 | int ret; | 1146 | int ret; |
1114 | 1147 | ||
1115 | wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", | 1148 | /* |
1116 | conf->bssid); | 1149 | * One of the side effects of the JOIN command is that is clears |
1117 | wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, | 1150 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated |
1118 | conf->ssid_len); | 1151 | * to a WPA/WPA2 access point will therefore kill the data-path. |
1152 | * Currently there is no supported scenario for JOIN during | ||
1153 | * association - if it becomes a supported scenario, the WPA/WPA2 keys | ||
1154 | * must be handled somehow. | ||
1155 | * | ||
1156 | */ | ||
1157 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1158 | wl1271_info("JOIN while associated."); | ||
1119 | 1159 | ||
1120 | mutex_lock(&wl->mutex); | 1160 | if (set_assoc) |
1161 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1121 | 1162 | ||
1122 | ret = wl1271_ps_elp_wakeup(wl, false); | 1163 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1123 | if (ret < 0) | 1164 | if (ret < 0) |
1124 | goto out; | 1165 | goto out; |
1125 | 1166 | ||
1126 | if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { | 1167 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1127 | wl1271_debug(DEBUG_MAC80211, "bssid changed"); | ||
1128 | |||
1129 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | ||
1130 | |||
1131 | ret = wl1271_cmd_join(wl); | ||
1132 | if (ret < 0) | ||
1133 | goto out_sleep; | ||
1134 | |||
1135 | ret = wl1271_cmd_build_null_data(wl); | ||
1136 | if (ret < 0) | ||
1137 | goto out_sleep; | ||
1138 | } | ||
1139 | |||
1140 | wl->ssid_len = conf->ssid_len; | ||
1141 | if (wl->ssid_len) | ||
1142 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); | ||
1143 | |||
1144 | if (conf->changed & IEEE80211_IFCC_BEACON) { | ||
1145 | beacon = ieee80211_beacon_get(hw, vif); | ||
1146 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1147 | beacon->data, beacon->len); | ||
1148 | |||
1149 | if (ret < 0) { | ||
1150 | dev_kfree_skb(beacon); | ||
1151 | goto out_sleep; | ||
1152 | } | ||
1153 | |||
1154 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, | ||
1155 | beacon->data, beacon->len); | ||
1156 | |||
1157 | dev_kfree_skb(beacon); | ||
1158 | |||
1159 | if (ret < 0) | ||
1160 | goto out_sleep; | ||
1161 | } | ||
1162 | |||
1163 | out_sleep: | ||
1164 | wl1271_ps_elp_sleep(wl); | ||
1165 | |||
1166 | out: | ||
1167 | mutex_unlock(&wl->mutex); | ||
1168 | |||
1169 | return ret; | ||
1170 | } | ||
1171 | #endif | ||
1172 | |||
1173 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1174 | { | ||
1175 | int ret = 0; | ||
1176 | /* we need to use a dummy BSSID for now */ | ||
1177 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1178 | 0xad, 0xbe, 0xef }; | ||
1179 | 1168 | ||
1180 | /* the dummy join is not required for ad-hoc */ | 1169 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1181 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1182 | goto out; | 1170 | goto out; |
1183 | 1171 | ||
1184 | /* disable mac filter, so we hear everything */ | 1172 | /* |
1185 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | 1173 | * The join command disable the keep-alive mode, shut down its process, |
1174 | * and also clear the template config, so we need to reset it all after | ||
1175 | * the join. The acx_aid starts the keep-alive process, and the order | ||
1176 | * of the commands below is relevant. | ||
1177 | */ | ||
1178 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1179 | if (ret < 0) | ||
1180 | goto out; | ||
1186 | 1181 | ||
1187 | wl->channel = channel; | 1182 | ret = wl1271_acx_aid(wl, wl->aid); |
1188 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1183 | if (ret < 0) |
1184 | goto out; | ||
1189 | 1185 | ||
1190 | ret = wl1271_cmd_join(wl); | 1186 | ret = wl1271_cmd_build_klv_null_data(wl); |
1191 | if (ret < 0) | 1187 | if (ret < 0) |
1192 | goto out; | 1188 | goto out; |
1193 | 1189 | ||
1194 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1190 | ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, |
1191 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1192 | if (ret < 0) | ||
1193 | goto out; | ||
1195 | 1194 | ||
1196 | out: | 1195 | out: |
1197 | return ret; | 1196 | return ret; |
1198 | } | 1197 | } |
1199 | 1198 | ||
1200 | static int wl1271_unjoin_channel(struct wl1271 *wl) | 1199 | static int wl1271_unjoin(struct wl1271 *wl) |
1201 | { | 1200 | { |
1202 | int ret; | 1201 | int ret; |
1203 | 1202 | ||
@@ -1207,14 +1206,41 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) | |||
1207 | goto out; | 1206 | goto out; |
1208 | 1207 | ||
1209 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
1210 | wl->channel = 0; | ||
1211 | memset(wl->bssid, 0, ETH_ALEN); | 1209 | memset(wl->bssid, 0, ETH_ALEN); |
1212 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1210 | |
1211 | /* stop filterting packets based on bssid */ | ||
1212 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1213 | 1213 | ||
1214 | out: | 1214 | out: |
1215 | return ret; | 1215 | return ret; |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1219 | { | ||
1220 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1221 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1222 | else | ||
1223 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1224 | } | ||
1225 | |||
1226 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1227 | { | ||
1228 | int i; | ||
1229 | u32 rate = 0; | ||
1230 | |||
1231 | if (!wl->basic_rate_set) { | ||
1232 | WARN_ON(1); | ||
1233 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1234 | } | ||
1235 | |||
1236 | for (i = 0; !rate; i++) { | ||
1237 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1238 | rate = 1 << i; | ||
1239 | } | ||
1240 | |||
1241 | return rate; | ||
1242 | } | ||
1243 | |||
1218 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1244 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1219 | { | 1245 | { |
1220 | struct wl1271 *wl = hw->priv; | 1246 | struct wl1271 *wl = hw->priv; |
@@ -1231,38 +1257,62 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1231 | 1257 | ||
1232 | mutex_lock(&wl->mutex); | 1258 | mutex_lock(&wl->mutex); |
1233 | 1259 | ||
1234 | wl->band = conf->channel->band; | 1260 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
1261 | goto out; | ||
1235 | 1262 | ||
1236 | ret = wl1271_ps_elp_wakeup(wl, false); | 1263 | ret = wl1271_ps_elp_wakeup(wl, false); |
1237 | if (ret < 0) | 1264 | if (ret < 0) |
1238 | goto out; | 1265 | goto out; |
1239 | 1266 | ||
1267 | /* if the channel changes while joined, join again */ | ||
1268 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | ||
1269 | ((wl->band != conf->channel->band) || | ||
1270 | (wl->channel != channel))) { | ||
1271 | wl->band = conf->channel->band; | ||
1272 | wl->channel = channel; | ||
1273 | |||
1274 | /* | ||
1275 | * FIXME: the mac80211 should really provide a fixed rate | ||
1276 | * to use here. for now, just use the smallest possible rate | ||
1277 | * for the band as a fixed rate for association frames and | ||
1278 | * other control messages. | ||
1279 | */ | ||
1280 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1281 | wl1271_set_band_rate(wl); | ||
1282 | |||
1283 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1284 | ret = wl1271_acx_rate_policies(wl); | ||
1285 | if (ret < 0) | ||
1286 | wl1271_warning("rate policy for update channel " | ||
1287 | "failed %d", ret); | ||
1288 | |||
1289 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1290 | ret = wl1271_join(wl, false); | ||
1291 | if (ret < 0) | ||
1292 | wl1271_warning("cmd join to update channel " | ||
1293 | "failed %d", ret); | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1240 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1297 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1241 | if (conf->flags & IEEE80211_CONF_IDLE && | 1298 | if (conf->flags & IEEE80211_CONF_IDLE && |
1242 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1299 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1243 | wl1271_unjoin_channel(wl); | 1300 | wl1271_unjoin(wl); |
1244 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) | 1301 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1245 | wl1271_join_channel(wl, channel); | 1302 | wl1271_dummy_join(wl); |
1246 | 1303 | ||
1247 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1304 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1248 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1305 | wl->rate_set = wl1271_min_rate_get(wl); |
1249 | wl->sta_rate_set = 0; | 1306 | wl->sta_rate_set = 0; |
1250 | wl1271_acx_rate_policies(wl); | 1307 | wl1271_acx_rate_policies(wl); |
1251 | } | 1308 | wl1271_acx_keep_alive_config( |
1309 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1310 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1311 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1312 | } else | ||
1313 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1252 | } | 1314 | } |
1253 | 1315 | ||
1254 | /* if the channel changes while joined, join again */ | ||
1255 | if (channel != wl->channel && | ||
1256 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1257 | wl->channel = channel; | ||
1258 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1259 | ret = wl1271_cmd_join(wl); | ||
1260 | if (ret < 0) | ||
1261 | wl1271_warning("cmd join to update channel failed %d", | ||
1262 | ret); | ||
1263 | } else | ||
1264 | wl->channel = channel; | ||
1265 | |||
1266 | if (conf->flags & IEEE80211_CONF_PS && | 1316 | if (conf->flags & IEEE80211_CONF_PS && |
1267 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1317 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1268 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1318 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1273,13 +1323,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1273 | * through the bss_info_changed() hook. | 1323 | * through the bss_info_changed() hook. |
1274 | */ | 1324 | */ |
1275 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1325 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1276 | wl1271_info("psm enabled"); | 1326 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1277 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1327 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1278 | true); | 1328 | true); |
1279 | } | 1329 | } |
1280 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1330 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1281 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1331 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1282 | wl1271_info("psm disabled"); | 1332 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
1283 | 1333 | ||
1284 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1334 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1285 | 1335 | ||
@@ -1311,11 +1361,15 @@ struct wl1271_filter_params { | |||
1311 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; | 1361 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; |
1312 | }; | 1362 | }; |
1313 | 1363 | ||
1314 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | 1364 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, |
1315 | struct dev_addr_list *mc_list) | 1365 | struct netdev_hw_addr_list *mc_list) |
1316 | { | 1366 | { |
1317 | struct wl1271_filter_params *fp; | 1367 | struct wl1271_filter_params *fp; |
1318 | int i; | 1368 | struct netdev_hw_addr *ha; |
1369 | struct wl1271 *wl = hw->priv; | ||
1370 | |||
1371 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1372 | return 0; | ||
1319 | 1373 | ||
1320 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1374 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1321 | if (!fp) { | 1375 | if (!fp) { |
@@ -1324,21 +1378,16 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | |||
1324 | } | 1378 | } |
1325 | 1379 | ||
1326 | /* update multicast filtering parameters */ | 1380 | /* update multicast filtering parameters */ |
1327 | fp->enabled = true; | ||
1328 | if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { | ||
1329 | mc_count = 0; | ||
1330 | fp->enabled = false; | ||
1331 | } | ||
1332 | |||
1333 | fp->mc_list_length = 0; | 1381 | fp->mc_list_length = 0; |
1334 | for (i = 0; i < mc_count; i++) { | 1382 | if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { |
1335 | if (mc_list->da_addrlen == ETH_ALEN) { | 1383 | fp->enabled = false; |
1384 | } else { | ||
1385 | fp->enabled = true; | ||
1386 | netdev_hw_addr_list_for_each(ha, mc_list) { | ||
1336 | memcpy(fp->mc_list[fp->mc_list_length], | 1387 | memcpy(fp->mc_list[fp->mc_list_length], |
1337 | mc_list->da_addr, ETH_ALEN); | 1388 | ha->addr, ETH_ALEN); |
1338 | fp->mc_list_length++; | 1389 | fp->mc_list_length++; |
1339 | } else | 1390 | } |
1340 | wl1271_warning("Unknown mc address length."); | ||
1341 | mc_list = mc_list->next; | ||
1342 | } | 1391 | } |
1343 | 1392 | ||
1344 | return (u64)(unsigned long)fp; | 1393 | return (u64)(unsigned long)fp; |
@@ -1363,15 +1412,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1363 | 1412 | ||
1364 | mutex_lock(&wl->mutex); | 1413 | mutex_lock(&wl->mutex); |
1365 | 1414 | ||
1366 | if (wl->state == WL1271_STATE_OFF) | 1415 | *total &= WL1271_SUPPORTED_FILTERS; |
1416 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1417 | |||
1418 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1367 | goto out; | 1419 | goto out; |
1368 | 1420 | ||
1369 | ret = wl1271_ps_elp_wakeup(wl, false); | 1421 | ret = wl1271_ps_elp_wakeup(wl, false); |
1370 | if (ret < 0) | 1422 | if (ret < 0) |
1371 | goto out; | 1423 | goto out; |
1372 | 1424 | ||
1373 | *total &= WL1271_SUPPORTED_FILTERS; | ||
1374 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1375 | 1425 | ||
1376 | if (*total & FIF_ALLMULTI) | 1426 | if (*total & FIF_ALLMULTI) |
1377 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1427 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
@@ -1382,14 +1432,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1382 | if (ret < 0) | 1432 | if (ret < 0) |
1383 | goto out_sleep; | 1433 | goto out_sleep; |
1384 | 1434 | ||
1385 | kfree(fp); | ||
1386 | |||
1387 | /* FIXME: We still need to set our filters properly */ | ||
1388 | |||
1389 | /* determine, whether supported filter values have changed */ | 1435 | /* determine, whether supported filter values have changed */ |
1390 | if (changed == 0) | 1436 | if (changed == 0) |
1391 | goto out_sleep; | 1437 | goto out_sleep; |
1392 | 1438 | ||
1439 | /* configure filters */ | ||
1440 | wl->filters = *total; | ||
1441 | wl1271_configure_filters(wl, 0); | ||
1442 | |||
1393 | /* apply configured filters */ | 1443 | /* apply configured filters */ |
1394 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | 1444 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
1395 | if (ret < 0) | 1445 | if (ret < 0) |
@@ -1400,6 +1450,7 @@ out_sleep: | |||
1400 | 1450 | ||
1401 | out: | 1451 | out: |
1402 | mutex_unlock(&wl->mutex); | 1452 | mutex_unlock(&wl->mutex); |
1453 | kfree(fp); | ||
1403 | } | 1454 | } |
1404 | 1455 | ||
1405 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1456 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -1450,15 +1501,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1450 | key_type = KEY_TKIP; | 1501 | key_type = KEY_TKIP; |
1451 | 1502 | ||
1452 | key_conf->hw_key_idx = key_conf->keyidx; | 1503 | key_conf->hw_key_idx = key_conf->keyidx; |
1453 | tx_seq_32 = wl->tx_security_seq_32; | 1504 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1454 | tx_seq_16 = wl->tx_security_seq_16; | 1505 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1455 | break; | 1506 | break; |
1456 | case ALG_CCMP: | 1507 | case ALG_CCMP: |
1457 | key_type = KEY_AES; | 1508 | key_type = KEY_AES; |
1458 | 1509 | ||
1459 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1510 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1460 | tx_seq_32 = wl->tx_security_seq_32; | 1511 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1461 | tx_seq_16 = wl->tx_security_seq_16; | 1512 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1462 | break; | 1513 | break; |
1463 | default: | 1514 | default: |
1464 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1515 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -1508,8 +1559,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1508 | default: | 1559 | default: |
1509 | wl1271_error("Unsupported key cmd 0x%x", cmd); | 1560 | wl1271_error("Unsupported key cmd 0x%x", cmd); |
1510 | ret = -EOPNOTSUPP; | 1561 | ret = -EOPNOTSUPP; |
1511 | goto out_sleep; | ||
1512 | |||
1513 | break; | 1562 | break; |
1514 | } | 1563 | } |
1515 | 1564 | ||
@@ -1524,6 +1573,7 @@ out: | |||
1524 | } | 1573 | } |
1525 | 1574 | ||
1526 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | 1575 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, |
1576 | struct ieee80211_vif *vif, | ||
1527 | struct cfg80211_scan_request *req) | 1577 | struct cfg80211_scan_request *req) |
1528 | { | 1578 | { |
1529 | struct wl1271 *wl = hw->priv; | 1579 | struct wl1271 *wl = hw->priv; |
@@ -1545,10 +1595,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1545 | goto out; | 1595 | goto out; |
1546 | 1596 | ||
1547 | if (wl1271_11a_enabled()) | 1597 | if (wl1271_11a_enabled()) |
1548 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1598 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1599 | req->ie, req->ie_len, 1, 0, | ||
1549 | WL1271_SCAN_BAND_DUAL, 3); | 1600 | WL1271_SCAN_BAND_DUAL, 3); |
1550 | else | 1601 | else |
1551 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1602 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1603 | req->ie, req->ie_len, 1, 0, | ||
1552 | WL1271_SCAN_BAND_2_4_GHZ, 3); | 1604 | WL1271_SCAN_BAND_2_4_GHZ, 3); |
1553 | 1605 | ||
1554 | wl1271_ps_elp_sleep(wl); | 1606 | wl1271_ps_elp_sleep(wl); |
@@ -1562,10 +1614,13 @@ out: | |||
1562 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1614 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1563 | { | 1615 | { |
1564 | struct wl1271 *wl = hw->priv; | 1616 | struct wl1271 *wl = hw->priv; |
1565 | int ret; | 1617 | int ret = 0; |
1566 | 1618 | ||
1567 | mutex_lock(&wl->mutex); | 1619 | mutex_lock(&wl->mutex); |
1568 | 1620 | ||
1621 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1622 | goto out; | ||
1623 | |||
1569 | ret = wl1271_ps_elp_wakeup(wl, false); | 1624 | ret = wl1271_ps_elp_wakeup(wl, false); |
1570 | if (ret < 0) | 1625 | if (ret < 0) |
1571 | goto out; | 1626 | goto out; |
@@ -1607,6 +1662,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1607 | enum wl1271_cmd_ps_mode mode; | 1662 | enum wl1271_cmd_ps_mode mode; |
1608 | struct wl1271 *wl = hw->priv; | 1663 | struct wl1271 *wl = hw->priv; |
1609 | bool do_join = false; | 1664 | bool do_join = false; |
1665 | bool set_assoc = false; | ||
1610 | int ret; | 1666 | int ret; |
1611 | 1667 | ||
1612 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1668 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1617,20 +1673,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1617 | if (ret < 0) | 1673 | if (ret < 0) |
1618 | goto out; | 1674 | goto out; |
1619 | 1675 | ||
1620 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1676 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1621 | /* FIXME: This implements rudimentary ad-hoc support - | 1677 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1622 | proper templates are on the wish list and notification | 1678 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1623 | on when they change. This patch will update the templates | 1679 | bss_conf->beacon_int); |
1624 | on every call to this function. */ | 1680 | |
1681 | wl->beacon_int = bss_conf->beacon_int; | ||
1682 | do_join = true; | ||
1683 | } | ||
1684 | |||
1685 | if ((changed && BSS_CHANGED_BEACON) && | ||
1686 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1625 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1687 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1626 | 1688 | ||
1689 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1690 | |||
1627 | if (beacon) { | 1691 | if (beacon) { |
1628 | struct ieee80211_hdr *hdr; | 1692 | struct ieee80211_hdr *hdr; |
1629 | 1693 | ||
1630 | wl1271_ssid_set(wl, beacon); | 1694 | wl1271_ssid_set(wl, beacon); |
1631 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1695 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1632 | beacon->data, | 1696 | beacon->data, |
1633 | beacon->len); | 1697 | beacon->len, 0, |
1698 | wl1271_min_rate_get(wl)); | ||
1634 | 1699 | ||
1635 | if (ret < 0) { | 1700 | if (ret < 0) { |
1636 | dev_kfree_skb(beacon); | 1701 | dev_kfree_skb(beacon); |
@@ -1645,7 +1710,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1645 | ret = wl1271_cmd_template_set(wl, | 1710 | ret = wl1271_cmd_template_set(wl, |
1646 | CMD_TEMPL_PROBE_RESPONSE, | 1711 | CMD_TEMPL_PROBE_RESPONSE, |
1647 | beacon->data, | 1712 | beacon->data, |
1648 | beacon->len); | 1713 | beacon->len, 0, |
1714 | wl1271_min_rate_get(wl)); | ||
1649 | dev_kfree_skb(beacon); | 1715 | dev_kfree_skb(beacon); |
1650 | if (ret < 0) | 1716 | if (ret < 0) |
1651 | goto out_sleep; | 1717 | goto out_sleep; |
@@ -1655,20 +1721,48 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1655 | } | 1721 | } |
1656 | } | 1722 | } |
1657 | 1723 | ||
1724 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1725 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1726 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1727 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1728 | |||
1729 | if (bss_conf->enable_beacon) | ||
1730 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1731 | else | ||
1732 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1733 | do_join = true; | ||
1734 | } | ||
1735 | |||
1736 | if (changed & BSS_CHANGED_CQM) { | ||
1737 | bool enable = false; | ||
1738 | if (bss_conf->cqm_rssi_thold) | ||
1739 | enable = true; | ||
1740 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | ||
1741 | bss_conf->cqm_rssi_thold, | ||
1742 | bss_conf->cqm_rssi_hyst); | ||
1743 | if (ret < 0) | ||
1744 | goto out; | ||
1745 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
1746 | } | ||
1747 | |||
1658 | if ((changed & BSS_CHANGED_BSSID) && | 1748 | if ((changed & BSS_CHANGED_BSSID) && |
1659 | /* | 1749 | /* |
1660 | * Now we know the correct bssid, so we send a new join command | 1750 | * Now we know the correct bssid, so we send a new join command |
1661 | * and enable the BSSID filter | 1751 | * and enable the BSSID filter |
1662 | */ | 1752 | */ |
1663 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 1753 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1664 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1665 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 1754 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1755 | |||
1666 | ret = wl1271_cmd_build_null_data(wl); | 1756 | ret = wl1271_cmd_build_null_data(wl); |
1667 | if (ret < 0) { | 1757 | if (ret < 0) |
1668 | wl1271_warning("cmd buld null data failed %d", | 1758 | goto out_sleep; |
1669 | ret); | 1759 | |
1760 | ret = wl1271_build_qos_null_data(wl); | ||
1761 | if (ret < 0) | ||
1670 | goto out_sleep; | 1762 | goto out_sleep; |
1671 | } | 1763 | |
1764 | /* filter out all packets not from this BSSID */ | ||
1765 | wl1271_configure_filters(wl, 0); | ||
1672 | 1766 | ||
1673 | /* Need to update the BSSID (for filtering etc) */ | 1767 | /* Need to update the BSSID (for filtering etc) */ |
1674 | do_join = true; | 1768 | do_join = true; |
@@ -1676,8 +1770,21 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1676 | 1770 | ||
1677 | if (changed & BSS_CHANGED_ASSOC) { | 1771 | if (changed & BSS_CHANGED_ASSOC) { |
1678 | if (bss_conf->assoc) { | 1772 | if (bss_conf->assoc) { |
1773 | u32 rates; | ||
1679 | wl->aid = bss_conf->aid; | 1774 | wl->aid = bss_conf->aid; |
1680 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1775 | set_assoc = true; |
1776 | |||
1777 | /* | ||
1778 | * use basic rates from AP, and determine lowest rate | ||
1779 | * to use with control frames. | ||
1780 | */ | ||
1781 | rates = bss_conf->basic_rates; | ||
1782 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1783 | rates); | ||
1784 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1785 | ret = wl1271_acx_rate_policies(wl); | ||
1786 | if (ret < 0) | ||
1787 | goto out_sleep; | ||
1681 | 1788 | ||
1682 | /* | 1789 | /* |
1683 | * with wl1271, we don't need to update the | 1790 | * with wl1271, we don't need to update the |
@@ -1689,7 +1796,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1689 | if (ret < 0) | 1796 | if (ret < 0) |
1690 | goto out_sleep; | 1797 | goto out_sleep; |
1691 | 1798 | ||
1692 | ret = wl1271_acx_aid(wl, wl->aid); | 1799 | /* |
1800 | * The SSID is intentionally set to NULL here - the | ||
1801 | * firmware will set the probe request with a | ||
1802 | * broadcast SSID regardless of what we set in the | ||
1803 | * template. | ||
1804 | */ | ||
1805 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1806 | NULL, 0, wl->band); | ||
1807 | |||
1808 | /* enable the connection monitoring feature */ | ||
1809 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1693 | if (ret < 0) | 1810 | if (ret < 0) |
1694 | goto out_sleep; | 1811 | goto out_sleep; |
1695 | 1812 | ||
@@ -1705,6 +1822,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1705 | /* use defaults when not associated */ | 1822 | /* use defaults when not associated */ |
1706 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1823 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1707 | wl->aid = 0; | 1824 | wl->aid = 0; |
1825 | |||
1826 | /* revert back to minimum rates for the current band */ | ||
1827 | wl1271_set_band_rate(wl); | ||
1828 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1829 | ret = wl1271_acx_rate_policies(wl); | ||
1830 | if (ret < 0) | ||
1831 | goto out_sleep; | ||
1832 | |||
1833 | /* disable connection monitor features */ | ||
1834 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1835 | |||
1836 | /* Disable the keep-alive feature */ | ||
1837 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1838 | |||
1839 | if (ret < 0) | ||
1840 | goto out_sleep; | ||
1708 | } | 1841 | } |
1709 | 1842 | ||
1710 | } | 1843 | } |
@@ -1739,12 +1872,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1739 | } | 1872 | } |
1740 | 1873 | ||
1741 | if (do_join) { | 1874 | if (do_join) { |
1742 | ret = wl1271_cmd_join(wl); | 1875 | ret = wl1271_join(wl, set_assoc); |
1743 | if (ret < 0) { | 1876 | if (ret < 0) { |
1744 | wl1271_warning("cmd join failed %d", ret); | 1877 | wl1271_warning("cmd join failed %d", ret); |
1745 | goto out_sleep; | 1878 | goto out_sleep; |
1746 | } | 1879 | } |
1747 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1748 | } | 1880 | } |
1749 | 1881 | ||
1750 | out_sleep: | 1882 | out_sleep: |
@@ -1758,6 +1890,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1758 | const struct ieee80211_tx_queue_params *params) | 1890 | const struct ieee80211_tx_queue_params *params) |
1759 | { | 1891 | { |
1760 | struct wl1271 *wl = hw->priv; | 1892 | struct wl1271 *wl = hw->priv; |
1893 | u8 ps_scheme; | ||
1761 | int ret; | 1894 | int ret; |
1762 | 1895 | ||
1763 | mutex_lock(&wl->mutex); | 1896 | mutex_lock(&wl->mutex); |
@@ -1768,17 +1901,22 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1768 | if (ret < 0) | 1901 | if (ret < 0) |
1769 | goto out; | 1902 | goto out; |
1770 | 1903 | ||
1904 | /* the txop is confed in units of 32us by the mac80211, we need us */ | ||
1771 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 1905 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
1772 | params->cw_min, params->cw_max, | 1906 | params->cw_min, params->cw_max, |
1773 | params->aifs, params->txop); | 1907 | params->aifs, params->txop << 5); |
1774 | if (ret < 0) | 1908 | if (ret < 0) |
1775 | goto out_sleep; | 1909 | goto out_sleep; |
1776 | 1910 | ||
1911 | if (params->uapsd) | ||
1912 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | ||
1913 | else | ||
1914 | ps_scheme = CONF_PS_SCHEME_LEGACY; | ||
1915 | |||
1777 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 1916 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), |
1778 | CONF_CHANNEL_TYPE_EDCF, | 1917 | CONF_CHANNEL_TYPE_EDCF, |
1779 | wl1271_tx_get_queue(queue), | 1918 | wl1271_tx_get_queue(queue), |
1780 | CONF_PS_SCHEME_LEGACY_PSPOLL, | 1919 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); |
1781 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1782 | if (ret < 0) | 1920 | if (ret < 0) |
1783 | goto out_sleep; | 1921 | goto out_sleep; |
1784 | 1922 | ||
@@ -1852,6 +1990,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1852 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1990 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1853 | }; | 1991 | }; |
1854 | 1992 | ||
1993 | /* mapping to indexes for wl1271_rates */ | ||
1994 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1995 | /* MCS rates are used only with 11n */ | ||
1996 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1997 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1998 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1999 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2000 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2001 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2002 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2003 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2004 | |||
2005 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
2006 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
2007 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
2008 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
2009 | |||
2010 | /* TI-specific rate */ | ||
2011 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2012 | |||
2013 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
2014 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
2015 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
2016 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
2017 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
2018 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2019 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
2020 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
2021 | }; | ||
2022 | |||
1855 | /* can't be const, mac80211 writes to this */ | 2023 | /* can't be const, mac80211 writes to this */ |
1856 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2024 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1857 | .channels = wl1271_channels, | 2025 | .channels = wl1271_channels, |
@@ -1934,6 +2102,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1934 | { .hw_value = 165, .center_freq = 5825}, | 2102 | { .hw_value = 165, .center_freq = 5825}, |
1935 | }; | 2103 | }; |
1936 | 2104 | ||
2105 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2106 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2107 | /* MCS rates are used only with 11n */ | ||
2108 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2112 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2113 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2114 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2115 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2116 | |||
2117 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2118 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2119 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2120 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2121 | |||
2122 | /* TI-specific rate */ | ||
2123 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2124 | |||
2125 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2126 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2127 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2128 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2129 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2130 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2131 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2132 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2133 | }; | ||
1937 | 2134 | ||
1938 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2135 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1939 | .channels = wl1271_channels_5ghz, | 2136 | .channels = wl1271_channels_5ghz, |
@@ -1942,13 +2139,17 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1942 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2139 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1943 | }; | 2140 | }; |
1944 | 2141 | ||
2142 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2143 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2144 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2145 | }; | ||
2146 | |||
1945 | static const struct ieee80211_ops wl1271_ops = { | 2147 | static const struct ieee80211_ops wl1271_ops = { |
1946 | .start = wl1271_op_start, | 2148 | .start = wl1271_op_start, |
1947 | .stop = wl1271_op_stop, | 2149 | .stop = wl1271_op_stop, |
1948 | .add_interface = wl1271_op_add_interface, | 2150 | .add_interface = wl1271_op_add_interface, |
1949 | .remove_interface = wl1271_op_remove_interface, | 2151 | .remove_interface = wl1271_op_remove_interface, |
1950 | .config = wl1271_op_config, | 2152 | .config = wl1271_op_config, |
1951 | /* .config_interface = wl1271_op_config_interface, */ | ||
1952 | .prepare_multicast = wl1271_op_prepare_multicast, | 2153 | .prepare_multicast = wl1271_op_prepare_multicast, |
1953 | .configure_filter = wl1271_op_configure_filter, | 2154 | .configure_filter = wl1271_op_configure_filter, |
1954 | .tx = wl1271_op_tx, | 2155 | .tx = wl1271_op_tx, |
@@ -1960,7 +2161,113 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1960 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2161 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1961 | }; | 2162 | }; |
1962 | 2163 | ||
1963 | static int wl1271_register_hw(struct wl1271 *wl) | 2164 | |
2165 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2166 | { | ||
2167 | u8 idx; | ||
2168 | |||
2169 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2170 | |||
2171 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2172 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2173 | return 0; | ||
2174 | } | ||
2175 | |||
2176 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2177 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2178 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2179 | return 0; | ||
2180 | } | ||
2181 | |||
2182 | return idx; | ||
2183 | } | ||
2184 | |||
2185 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | ||
2186 | struct device_attribute *attr, | ||
2187 | char *buf) | ||
2188 | { | ||
2189 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2190 | ssize_t len; | ||
2191 | |||
2192 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
2193 | len = 500; | ||
2194 | |||
2195 | mutex_lock(&wl->mutex); | ||
2196 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | ||
2197 | wl->sg_enabled); | ||
2198 | mutex_unlock(&wl->mutex); | ||
2199 | |||
2200 | return len; | ||
2201 | |||
2202 | } | ||
2203 | |||
2204 | static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | ||
2205 | struct device_attribute *attr, | ||
2206 | const char *buf, size_t count) | ||
2207 | { | ||
2208 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2209 | unsigned long res; | ||
2210 | int ret; | ||
2211 | |||
2212 | ret = strict_strtoul(buf, 10, &res); | ||
2213 | |||
2214 | if (ret < 0) { | ||
2215 | wl1271_warning("incorrect value written to bt_coex_mode"); | ||
2216 | return count; | ||
2217 | } | ||
2218 | |||
2219 | mutex_lock(&wl->mutex); | ||
2220 | |||
2221 | res = !!res; | ||
2222 | |||
2223 | if (res == wl->sg_enabled) | ||
2224 | goto out; | ||
2225 | |||
2226 | wl->sg_enabled = res; | ||
2227 | |||
2228 | if (wl->state == WL1271_STATE_OFF) | ||
2229 | goto out; | ||
2230 | |||
2231 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2232 | if (ret < 0) | ||
2233 | goto out; | ||
2234 | |||
2235 | wl1271_acx_sg_enable(wl, wl->sg_enabled); | ||
2236 | wl1271_ps_elp_sleep(wl); | ||
2237 | |||
2238 | out: | ||
2239 | mutex_unlock(&wl->mutex); | ||
2240 | return count; | ||
2241 | } | ||
2242 | |||
2243 | static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, | ||
2244 | wl1271_sysfs_show_bt_coex_state, | ||
2245 | wl1271_sysfs_store_bt_coex_state); | ||
2246 | |||
2247 | static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, | ||
2248 | struct device_attribute *attr, | ||
2249 | char *buf) | ||
2250 | { | ||
2251 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2252 | ssize_t len; | ||
2253 | |||
2254 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
2255 | len = 500; | ||
2256 | |||
2257 | mutex_lock(&wl->mutex); | ||
2258 | if (wl->hw_pg_ver >= 0) | ||
2259 | len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); | ||
2260 | else | ||
2261 | len = snprintf(buf, len, "n/a\n"); | ||
2262 | mutex_unlock(&wl->mutex); | ||
2263 | |||
2264 | return len; | ||
2265 | } | ||
2266 | |||
2267 | static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, | ||
2268 | wl1271_sysfs_show_hw_pg_ver, NULL); | ||
2269 | |||
2270 | int wl1271_register_hw(struct wl1271 *wl) | ||
1964 | { | 2271 | { |
1965 | int ret; | 2272 | int ret; |
1966 | 2273 | ||
@@ -1981,8 +2288,17 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1981 | 2288 | ||
1982 | return 0; | 2289 | return 0; |
1983 | } | 2290 | } |
2291 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
2292 | |||
2293 | void wl1271_unregister_hw(struct wl1271 *wl) | ||
2294 | { | ||
2295 | ieee80211_unregister_hw(wl->hw); | ||
2296 | wl->mac80211_registered = false; | ||
2297 | |||
2298 | } | ||
2299 | EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | ||
1984 | 2300 | ||
1985 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 2301 | int wl1271_init_ieee80211(struct wl1271 *wl) |
1986 | { | 2302 | { |
1987 | /* The tx descriptor buffer and the TKIP space. */ | 2303 | /* The tx descriptor buffer and the TKIP space. */ |
1988 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2304 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
@@ -1991,11 +2307,15 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1991 | /* unit us */ | 2307 | /* unit us */ |
1992 | /* FIXME: find a proper value */ | 2308 | /* FIXME: find a proper value */ |
1993 | wl->hw->channel_change_time = 10000; | 2309 | wl->hw->channel_change_time = 10000; |
2310 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
1994 | 2311 | ||
1995 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2312 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1996 | IEEE80211_HW_NOISE_DBM | | ||
1997 | IEEE80211_HW_BEACON_FILTER | | 2313 | IEEE80211_HW_BEACON_FILTER | |
1998 | IEEE80211_HW_SUPPORTS_PS; | 2314 | IEEE80211_HW_SUPPORTS_PS | |
2315 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
2316 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
2317 | IEEE80211_HW_CONNECTION_MONITOR | | ||
2318 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
1999 | 2319 | ||
2000 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2320 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2001 | BIT(NL80211_IFTYPE_ADHOC); | 2321 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2005,51 +2325,53 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2005 | if (wl1271_11a_enabled()) | 2325 | if (wl1271_11a_enabled()) |
2006 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2326 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2007 | 2327 | ||
2008 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 2328 | wl->hw->queues = 4; |
2329 | wl->hw->max_rates = 1; | ||
2009 | 2330 | ||
2010 | return 0; | 2331 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2011 | } | ||
2012 | |||
2013 | static void wl1271_device_release(struct device *dev) | ||
2014 | { | ||
2015 | 2332 | ||
2333 | return 0; | ||
2016 | } | 2334 | } |
2017 | 2335 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | |
2018 | static struct platform_device wl1271_device = { | ||
2019 | .name = "wl1271", | ||
2020 | .id = -1, | ||
2021 | |||
2022 | /* device model insists to have a release function */ | ||
2023 | .dev = { | ||
2024 | .release = wl1271_device_release, | ||
2025 | }, | ||
2026 | }; | ||
2027 | 2336 | ||
2028 | #define WL1271_DEFAULT_CHANNEL 0 | 2337 | #define WL1271_DEFAULT_CHANNEL 0 |
2029 | 2338 | ||
2030 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 2339 | struct ieee80211_hw *wl1271_alloc_hw(void) |
2031 | { | 2340 | { |
2032 | struct ieee80211_hw *hw; | 2341 | struct ieee80211_hw *hw; |
2342 | struct platform_device *plat_dev = NULL; | ||
2033 | struct wl1271 *wl; | 2343 | struct wl1271 *wl; |
2034 | int i; | 2344 | int i, ret; |
2035 | 2345 | ||
2036 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2346 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2037 | if (!hw) { | 2347 | if (!hw) { |
2038 | wl1271_error("could not alloc ieee80211_hw"); | 2348 | wl1271_error("could not alloc ieee80211_hw"); |
2039 | return ERR_PTR(-ENOMEM); | 2349 | ret = -ENOMEM; |
2350 | goto err_hw_alloc; | ||
2351 | } | ||
2352 | |||
2353 | plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); | ||
2354 | if (!plat_dev) { | ||
2355 | wl1271_error("could not allocate platform_device"); | ||
2356 | ret = -ENOMEM; | ||
2357 | goto err_plat_alloc; | ||
2040 | } | 2358 | } |
2041 | 2359 | ||
2360 | memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); | ||
2361 | |||
2042 | wl = hw->priv; | 2362 | wl = hw->priv; |
2043 | memset(wl, 0, sizeof(*wl)); | 2363 | memset(wl, 0, sizeof(*wl)); |
2044 | 2364 | ||
2045 | INIT_LIST_HEAD(&wl->list); | 2365 | INIT_LIST_HEAD(&wl->list); |
2046 | 2366 | ||
2047 | wl->hw = hw; | 2367 | wl->hw = hw; |
2368 | wl->plat_dev = plat_dev; | ||
2048 | 2369 | ||
2049 | skb_queue_head_init(&wl->tx_queue); | 2370 | skb_queue_head_init(&wl->tx_queue); |
2050 | 2371 | ||
2051 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2372 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2052 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2373 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2374 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2053 | wl->default_key = 0; | 2375 | wl->default_key = 0; |
2054 | wl->rx_counter = 0; | 2376 | wl->rx_counter = 0; |
2055 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2377 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2057,11 +2379,14 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2057 | wl->psm_entry_retry = 0; | 2379 | wl->psm_entry_retry = 0; |
2058 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2380 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2059 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2381 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2382 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2060 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2383 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2061 | wl->sta_rate_set = 0; | 2384 | wl->sta_rate_set = 0; |
2062 | wl->band = IEEE80211_BAND_2GHZ; | 2385 | wl->band = IEEE80211_BAND_2GHZ; |
2063 | wl->vif = NULL; | 2386 | wl->vif = NULL; |
2064 | wl->flags = 0; | 2387 | wl->flags = 0; |
2388 | wl->sg_enabled = true; | ||
2389 | wl->hw_pg_ver = -1; | ||
2065 | 2390 | ||
2066 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2391 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
2067 | wl->tx_frames[i] = NULL; | 2392 | wl->tx_frames[i] = NULL; |
@@ -2074,167 +2399,72 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2074 | /* Apply default driver configuration. */ | 2399 | /* Apply default driver configuration. */ |
2075 | wl1271_conf_init(wl); | 2400 | wl1271_conf_init(wl); |
2076 | 2401 | ||
2077 | return hw; | 2402 | wl1271_debugfs_init(wl); |
2078 | } | ||
2079 | |||
2080 | int wl1271_free_hw(struct wl1271 *wl) | ||
2081 | { | ||
2082 | ieee80211_unregister_hw(wl->hw); | ||
2083 | |||
2084 | wl1271_debugfs_exit(wl); | ||
2085 | |||
2086 | kfree(wl->target_mem_map); | ||
2087 | vfree(wl->fw); | ||
2088 | wl->fw = NULL; | ||
2089 | kfree(wl->nvs); | ||
2090 | wl->nvs = NULL; | ||
2091 | |||
2092 | kfree(wl->fw_status); | ||
2093 | kfree(wl->tx_res_if); | ||
2094 | |||
2095 | ieee80211_free_hw(wl->hw); | ||
2096 | |||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2101 | { | ||
2102 | struct wl12xx_platform_data *pdata; | ||
2103 | struct ieee80211_hw *hw; | ||
2104 | struct wl1271 *wl; | ||
2105 | int ret; | ||
2106 | 2403 | ||
2107 | pdata = spi->dev.platform_data; | 2404 | /* Register platform device */ |
2108 | if (!pdata) { | 2405 | ret = platform_device_register(wl->plat_dev); |
2109 | wl1271_error("no platform data"); | 2406 | if (ret) { |
2110 | return -ENODEV; | 2407 | wl1271_error("couldn't register platform device"); |
2408 | goto err_hw; | ||
2111 | } | 2409 | } |
2410 | dev_set_drvdata(&wl->plat_dev->dev, wl); | ||
2112 | 2411 | ||
2113 | hw = wl1271_alloc_hw(); | 2412 | /* Create sysfs file to control bt coex state */ |
2114 | if (IS_ERR(hw)) | 2413 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); |
2115 | return PTR_ERR(hw); | ||
2116 | |||
2117 | wl = hw->priv; | ||
2118 | |||
2119 | dev_set_drvdata(&spi->dev, wl); | ||
2120 | wl->spi = spi; | ||
2121 | |||
2122 | /* This is the only SPI value that we need to set here, the rest | ||
2123 | * comes from the board-peripherals file */ | ||
2124 | spi->bits_per_word = 32; | ||
2125 | |||
2126 | ret = spi_setup(spi); | ||
2127 | if (ret < 0) { | 2414 | if (ret < 0) { |
2128 | wl1271_error("spi_setup failed"); | 2415 | wl1271_error("failed to create sysfs file bt_coex_state"); |
2129 | goto out_free; | 2416 | goto err_platform; |
2130 | } | ||
2131 | |||
2132 | wl->set_power = pdata->set_power; | ||
2133 | if (!wl->set_power) { | ||
2134 | wl1271_error("set power function missing in platform data"); | ||
2135 | ret = -ENODEV; | ||
2136 | goto out_free; | ||
2137 | } | 2417 | } |
2138 | 2418 | ||
2139 | wl->irq = spi->irq; | 2419 | /* Create sysfs file to get HW PG version */ |
2140 | if (wl->irq < 0) { | 2420 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); |
2141 | wl1271_error("irq missing in platform data"); | ||
2142 | ret = -ENODEV; | ||
2143 | goto out_free; | ||
2144 | } | ||
2145 | |||
2146 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
2147 | if (ret < 0) { | 2421 | if (ret < 0) { |
2148 | wl1271_error("request_irq() failed: %d", ret); | 2422 | wl1271_error("failed to create sysfs file hw_pg_ver"); |
2149 | goto out_free; | 2423 | goto err_bt_coex_state; |
2150 | } | ||
2151 | |||
2152 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
2153 | |||
2154 | disable_irq(wl->irq); | ||
2155 | |||
2156 | ret = platform_device_register(&wl1271_device); | ||
2157 | if (ret) { | ||
2158 | wl1271_error("couldn't register platform device"); | ||
2159 | goto out_irq; | ||
2160 | } | 2424 | } |
2161 | dev_set_drvdata(&wl1271_device.dev, wl); | ||
2162 | |||
2163 | ret = wl1271_init_ieee80211(wl); | ||
2164 | if (ret) | ||
2165 | goto out_platform; | ||
2166 | |||
2167 | ret = wl1271_register_hw(wl); | ||
2168 | if (ret) | ||
2169 | goto out_platform; | ||
2170 | |||
2171 | wl1271_debugfs_init(wl); | ||
2172 | 2425 | ||
2173 | wl1271_notice("initialized"); | 2426 | return hw; |
2174 | 2427 | ||
2175 | return 0; | 2428 | err_bt_coex_state: |
2429 | device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
2176 | 2430 | ||
2177 | out_platform: | 2431 | err_platform: |
2178 | platform_device_unregister(&wl1271_device); | 2432 | platform_device_unregister(wl->plat_dev); |
2179 | 2433 | ||
2180 | out_irq: | 2434 | err_hw: |
2181 | free_irq(wl->irq, wl); | 2435 | wl1271_debugfs_exit(wl); |
2436 | kfree(plat_dev); | ||
2182 | 2437 | ||
2183 | out_free: | 2438 | err_plat_alloc: |
2184 | ieee80211_free_hw(hw); | 2439 | ieee80211_free_hw(hw); |
2185 | 2440 | ||
2186 | return ret; | 2441 | err_hw_alloc: |
2187 | } | ||
2188 | |||
2189 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
2190 | { | ||
2191 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
2192 | 2442 | ||
2193 | platform_device_unregister(&wl1271_device); | 2443 | return ERR_PTR(ret); |
2194 | free_irq(wl->irq, wl); | ||
2195 | |||
2196 | wl1271_free_hw(wl); | ||
2197 | |||
2198 | return 0; | ||
2199 | } | 2444 | } |
2445 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
2200 | 2446 | ||
2201 | 2447 | int wl1271_free_hw(struct wl1271 *wl) | |
2202 | static struct spi_driver wl1271_spi_driver = { | ||
2203 | .driver = { | ||
2204 | .name = "wl1271", | ||
2205 | .bus = &spi_bus_type, | ||
2206 | .owner = THIS_MODULE, | ||
2207 | }, | ||
2208 | |||
2209 | .probe = wl1271_probe, | ||
2210 | .remove = __devexit_p(wl1271_remove), | ||
2211 | }; | ||
2212 | |||
2213 | static int __init wl1271_init(void) | ||
2214 | { | 2448 | { |
2215 | int ret; | 2449 | platform_device_unregister(wl->plat_dev); |
2450 | kfree(wl->plat_dev); | ||
2216 | 2451 | ||
2217 | ret = spi_register_driver(&wl1271_spi_driver); | 2452 | wl1271_debugfs_exit(wl); |
2218 | if (ret < 0) { | ||
2219 | wl1271_error("failed to register spi driver: %d", ret); | ||
2220 | goto out; | ||
2221 | } | ||
2222 | 2453 | ||
2223 | out: | 2454 | vfree(wl->fw); |
2224 | return ret; | 2455 | wl->fw = NULL; |
2225 | } | 2456 | kfree(wl->nvs); |
2457 | wl->nvs = NULL; | ||
2226 | 2458 | ||
2227 | static void __exit wl1271_exit(void) | 2459 | kfree(wl->fw_status); |
2228 | { | 2460 | kfree(wl->tx_res_if); |
2229 | spi_unregister_driver(&wl1271_spi_driver); | ||
2230 | 2461 | ||
2231 | wl1271_notice("unloaded"); | 2462 | ieee80211_free_hw(wl->hw); |
2232 | } | ||
2233 | 2463 | ||
2234 | module_init(wl1271_init); | 2464 | return 0; |
2235 | module_exit(wl1271_exit); | 2465 | } |
2466 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | ||
2236 | 2467 | ||
2237 | MODULE_LICENSE("GPL"); | 2468 | MODULE_LICENSE("GPL"); |
2238 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2469 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2239 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2470 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
2240 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index e2b1ebf096e8..a5e60e0403e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include "wl1271_reg.h" | 24 | #include "wl1271_reg.h" |
25 | #include "wl1271_ps.h" | 25 | #include "wl1271_ps.h" |
26 | #include "wl1271_spi.h" | ||
27 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
28 | 27 | ||
29 | #define WL1271_WAKEUP_TIMEOUT 500 | 28 | #define WL1271_WAKEUP_TIMEOUT 500 |
@@ -41,7 +40,8 @@ void wl1271_elp_work(struct work_struct *work) | |||
41 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
42 | 41 | ||
43 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
44 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | 43 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
44 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | ||
45 | goto out; | 45 | goto out; |
46 | 46 | ||
47 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
@@ -57,7 +57,8 @@ out: | |||
57 | /* Routines to toggle sleep mode while in ELP */ | 57 | /* Routines to toggle sleep mode while in ELP */ |
58 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 58 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
59 | { | 59 | { |
60 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 60 | if (test_bit(WL1271_FLAG_PSM, &wl->flags) || |
61 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | ||
61 | cancel_delayed_work(&wl->elp_work); | 62 | cancel_delayed_work(&wl->elp_work); |
62 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 63 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
63 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 64 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index c723d9c7e131..57f4bfd959c8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "wl1271_acx.h" | 27 | #include "wl1271_acx.h" |
28 | #include "wl1271_reg.h" | 28 | #include "wl1271_reg.h" |
29 | #include "wl1271_rx.h" | 29 | #include "wl1271_rx.h" |
30 | #include "wl1271_spi.h" | ||
31 | #include "wl1271_io.h" | 30 | #include "wl1271_io.h" |
32 | 31 | ||
33 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 32 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
@@ -44,66 +43,6 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | |||
44 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | 43 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; |
45 | } | 44 | } |
46 | 45 | ||
47 | /* The values of this table must match the wl1271_rates[] array */ | ||
48 | static u8 wl1271_rx_rate_to_idx[] = { | ||
49 | /* MCS rates are used only with 11n */ | ||
50 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
51 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
52 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
53 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
54 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
55 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
56 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
57 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
58 | |||
59 | 11, /* WL1271_RATE_54 */ | ||
60 | 10, /* WL1271_RATE_48 */ | ||
61 | 9, /* WL1271_RATE_36 */ | ||
62 | 8, /* WL1271_RATE_24 */ | ||
63 | |||
64 | /* TI-specific rate */ | ||
65 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
66 | |||
67 | 7, /* WL1271_RATE_18 */ | ||
68 | 6, /* WL1271_RATE_12 */ | ||
69 | 3, /* WL1271_RATE_11 */ | ||
70 | 5, /* WL1271_RATE_9 */ | ||
71 | 4, /* WL1271_RATE_6 */ | ||
72 | 2, /* WL1271_RATE_5_5 */ | ||
73 | 1, /* WL1271_RATE_2 */ | ||
74 | 0 /* WL1271_RATE_1 */ | ||
75 | }; | ||
76 | |||
77 | /* The values of this table must match the wl1271_rates[] array */ | ||
78 | static u8 wl1271_5_ghz_rx_rate_to_idx[] = { | ||
79 | /* MCS rates are used only with 11n */ | ||
80 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
81 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
82 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
83 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
84 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
85 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
86 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
87 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
88 | |||
89 | 7, /* WL1271_RATE_54 */ | ||
90 | 6, /* WL1271_RATE_48 */ | ||
91 | 5, /* WL1271_RATE_36 */ | ||
92 | 4, /* WL1271_RATE_24 */ | ||
93 | |||
94 | /* TI-specific rate */ | ||
95 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
96 | |||
97 | 3, /* WL1271_RATE_18 */ | ||
98 | 2, /* WL1271_RATE_12 */ | ||
99 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ | ||
100 | 1, /* WL1271_RATE_9 */ | ||
101 | 0, /* WL1271_RATE_6 */ | ||
102 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ | ||
103 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ | ||
104 | WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ | ||
105 | }; | ||
106 | |||
107 | static void wl1271_rx_status(struct wl1271 *wl, | 46 | static void wl1271_rx_status(struct wl1271 *wl, |
108 | struct wl1271_rx_descriptor *desc, | 47 | struct wl1271_rx_descriptor *desc, |
109 | struct ieee80211_rx_status *status, | 48 | struct ieee80211_rx_status *status, |
@@ -111,20 +50,8 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
111 | { | 50 | { |
112 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 51 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
113 | 52 | ||
114 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | 53 | status->band = wl->band; |
115 | WL1271_RX_DESC_BAND_BG) { | 54 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); |
116 | status->band = IEEE80211_BAND_2GHZ; | ||
117 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; | ||
118 | } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | ||
119 | WL1271_RX_DESC_BAND_A) { | ||
120 | status->band = IEEE80211_BAND_5GHZ; | ||
121 | status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; | ||
122 | } else | ||
123 | wl1271_warning("unsupported band 0x%x", | ||
124 | desc->flags & WL1271_RX_DESC_BAND_MASK); | ||
125 | |||
126 | if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) | ||
127 | wl1271_warning("unsupported rate"); | ||
128 | 55 | ||
129 | /* | 56 | /* |
130 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | 57 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the |
@@ -134,13 +61,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
134 | */ | 61 | */ |
135 | status->signal = desc->rssi; | 62 | status->signal = desc->rssi; |
136 | 63 | ||
137 | /* | ||
138 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we | ||
139 | * need to divide by two for now, but TI has been discussing about | ||
140 | * changing it. This needs to be rechecked. | ||
141 | */ | ||
142 | status->noise = desc->rssi - (desc->snr >> 1); | ||
143 | |||
144 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 64 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
145 | 65 | ||
146 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 66 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
@@ -162,6 +82,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
162 | u8 *buf; | 82 | u8 *buf; |
163 | u8 beacon = 0; | 83 | u8 beacon = 0; |
164 | 84 | ||
85 | /* | ||
86 | * In PLT mode we seem to get frames and mac80211 warns about them, | ||
87 | * workaround this by not retrieving them at all. | ||
88 | */ | ||
89 | if (unlikely(wl->state == WL1271_STATE_PLT)) | ||
90 | return; | ||
91 | |||
165 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 92 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
166 | if (!skb) { | 93 | if (!skb) { |
167 | wl1271_error("Couldn't allocate RX frame"); | 94 | wl1271_error("Couldn't allocate RX frame"); |
@@ -220,6 +147,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
220 | 147 | ||
221 | wl->rx_counter++; | 148 | wl->rx_counter++; |
222 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 149 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
223 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
224 | } | 150 | } |
151 | |||
152 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
225 | } | 153 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index 1ae6d1783ed4..b89be4758e78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RX_MAX_PACKET_ID 3 | 43 | #define RX_MAX_PACKET_ID 3 |
44 | 44 | ||
45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 | 45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 |
46 | #define WL1271_RX_RATE_UNSUPPORTED 0xFF | ||
47 | 46 | ||
48 | #define RX_DESC_VALID_FCS 0x0001 | 47 | #define RX_DESC_VALID_FCS 0x0001 |
49 | #define RX_DESC_MATCH_RXADDR1 0x0002 | 48 | #define RX_DESC_MATCH_RXADDR1 0x0002 |
@@ -117,5 +116,6 @@ struct wl1271_rx_descriptor { | |||
117 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
118 | 117 | ||
119 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); | 118 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); |
119 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
120 | 120 | ||
121 | #endif | 121 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c new file mode 100644 index 000000000000..d3d6f302f705 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/irq.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/crc7.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/mmc/sdio_func.h> | ||
29 | #include <linux/mmc/sdio_ids.h> | ||
30 | #include <linux/mmc/card.h> | ||
31 | #include <plat/gpio.h> | ||
32 | |||
33 | #include "wl1271.h" | ||
34 | #include "wl12xx_80211.h" | ||
35 | #include "wl1271_io.h" | ||
36 | |||
37 | |||
38 | #define RX71_WL1271_IRQ_GPIO 42 | ||
39 | |||
40 | #ifndef SDIO_VENDOR_ID_TI | ||
41 | #define SDIO_VENDOR_ID_TI 0x0097 | ||
42 | #endif | ||
43 | |||
44 | #ifndef SDIO_DEVICE_ID_TI_WL1271 | ||
45 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | ||
46 | #endif | ||
47 | |||
48 | static const struct sdio_device_id wl1271_devices[] = { | ||
49 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, | ||
50 | {} | ||
51 | }; | ||
52 | MODULE_DEVICE_TABLE(sdio, wl1271_devices); | ||
53 | |||
54 | static inline struct sdio_func *wl_to_func(struct wl1271 *wl) | ||
55 | { | ||
56 | return wl->if_priv; | ||
57 | } | ||
58 | |||
59 | static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) | ||
60 | { | ||
61 | return &(wl_to_func(wl)->dev); | ||
62 | } | ||
63 | |||
64 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
65 | { | ||
66 | struct wl1271 *wl = cookie; | ||
67 | unsigned long flags; | ||
68 | |||
69 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
70 | |||
71 | /* complete the ELP completion */ | ||
72 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
73 | if (wl->elp_compl) { | ||
74 | complete(wl->elp_compl); | ||
75 | wl->elp_compl = NULL; | ||
76 | } | ||
77 | |||
78 | if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) | ||
79 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
80 | set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); | ||
81 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
82 | |||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | |||
86 | static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) | ||
87 | { | ||
88 | disable_irq(wl->irq); | ||
89 | } | ||
90 | |||
91 | static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) | ||
92 | { | ||
93 | enable_irq(wl->irq); | ||
94 | } | ||
95 | |||
96 | static void wl1271_sdio_reset(struct wl1271 *wl) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | static void wl1271_sdio_init(struct wl1271 *wl) | ||
101 | { | ||
102 | } | ||
103 | |||
104 | static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
105 | size_t len, bool fixed) | ||
106 | { | ||
107 | int ret; | ||
108 | struct sdio_func *func = wl_to_func(wl); | ||
109 | |||
110 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
111 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | ||
112 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", | ||
113 | addr, ((u8 *)buf)[0]); | ||
114 | } else { | ||
115 | if (fixed) | ||
116 | ret = sdio_readsb(func, buf, addr, len); | ||
117 | else | ||
118 | ret = sdio_memcpy_fromio(func, buf, addr, len); | ||
119 | |||
120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", | ||
121 | addr, len); | ||
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
123 | } | ||
124 | |||
125 | if (ret) | ||
126 | wl1271_error("sdio read failed (%d)", ret); | ||
127 | |||
128 | } | ||
129 | |||
130 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
131 | size_t len, bool fixed) | ||
132 | { | ||
133 | int ret; | ||
134 | struct sdio_func *func = wl_to_func(wl); | ||
135 | |||
136 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
137 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | ||
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | ||
139 | addr, ((u8 *)buf)[0]); | ||
140 | } else { | ||
141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", | ||
142 | addr, len); | ||
143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
144 | |||
145 | if (fixed) | ||
146 | ret = sdio_writesb(func, addr, buf, len); | ||
147 | else | ||
148 | ret = sdio_memcpy_toio(func, addr, buf, len); | ||
149 | } | ||
150 | if (ret) | ||
151 | wl1271_error("sdio write failed (%d)", ret); | ||
152 | |||
153 | } | ||
154 | |||
155 | static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | ||
156 | { | ||
157 | struct sdio_func *func = wl_to_func(wl); | ||
158 | |||
159 | /* Let the SDIO stack handle wlan_enable control, so we | ||
160 | * keep host claimed while wlan is in use to keep wl1271 | ||
161 | * alive. | ||
162 | */ | ||
163 | if (enable) { | ||
164 | sdio_claim_host(func); | ||
165 | sdio_enable_func(func); | ||
166 | } else { | ||
167 | sdio_disable_func(func); | ||
168 | sdio_release_host(func); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static struct wl1271_if_operations sdio_ops = { | ||
173 | .read = wl1271_sdio_raw_read, | ||
174 | .write = wl1271_sdio_raw_write, | ||
175 | .reset = wl1271_sdio_reset, | ||
176 | .init = wl1271_sdio_init, | ||
177 | .power = wl1271_sdio_set_power, | ||
178 | .dev = wl1271_sdio_wl_to_dev, | ||
179 | .enable_irq = wl1271_sdio_enable_interrupts, | ||
180 | .disable_irq = wl1271_sdio_disable_interrupts | ||
181 | }; | ||
182 | |||
183 | static int __devinit wl1271_probe(struct sdio_func *func, | ||
184 | const struct sdio_device_id *id) | ||
185 | { | ||
186 | struct ieee80211_hw *hw; | ||
187 | struct wl1271 *wl; | ||
188 | int ret; | ||
189 | |||
190 | /* We are only able to handle the wlan function */ | ||
191 | if (func->num != 0x02) | ||
192 | return -ENODEV; | ||
193 | |||
194 | hw = wl1271_alloc_hw(); | ||
195 | if (IS_ERR(hw)) | ||
196 | return PTR_ERR(hw); | ||
197 | |||
198 | wl = hw->priv; | ||
199 | |||
200 | wl->if_priv = func; | ||
201 | wl->if_ops = &sdio_ops; | ||
202 | |||
203 | /* Grab access to FN0 for ELP reg. */ | ||
204 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
205 | |||
206 | wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); | ||
207 | if (wl->irq < 0) { | ||
208 | ret = wl->irq; | ||
209 | wl1271_error("could not get irq!"); | ||
210 | goto out_free; | ||
211 | } | ||
212 | |||
213 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
214 | if (ret < 0) { | ||
215 | wl1271_error("request_irq() failed: %d", ret); | ||
216 | goto out_free; | ||
217 | } | ||
218 | |||
219 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
220 | |||
221 | disable_irq(wl->irq); | ||
222 | |||
223 | ret = wl1271_init_ieee80211(wl); | ||
224 | if (ret) | ||
225 | goto out_irq; | ||
226 | |||
227 | ret = wl1271_register_hw(wl); | ||
228 | if (ret) | ||
229 | goto out_irq; | ||
230 | |||
231 | sdio_set_drvdata(func, wl); | ||
232 | |||
233 | wl1271_notice("initialized"); | ||
234 | |||
235 | return 0; | ||
236 | |||
237 | out_irq: | ||
238 | free_irq(wl->irq, wl); | ||
239 | |||
240 | |||
241 | out_free: | ||
242 | wl1271_free_hw(wl); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static void __devexit wl1271_remove(struct sdio_func *func) | ||
248 | { | ||
249 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
250 | |||
251 | free_irq(wl->irq, wl); | ||
252 | |||
253 | wl1271_unregister_hw(wl); | ||
254 | wl1271_free_hw(wl); | ||
255 | } | ||
256 | |||
257 | static struct sdio_driver wl1271_sdio_driver = { | ||
258 | .name = "wl1271_sdio", | ||
259 | .id_table = wl1271_devices, | ||
260 | .probe = wl1271_probe, | ||
261 | .remove = __devexit_p(wl1271_remove), | ||
262 | }; | ||
263 | |||
264 | static int __init wl1271_init(void) | ||
265 | { | ||
266 | int ret; | ||
267 | |||
268 | ret = sdio_register_driver(&wl1271_sdio_driver); | ||
269 | if (ret < 0) { | ||
270 | wl1271_error("failed to register sdio driver: %d", ret); | ||
271 | goto out; | ||
272 | } | ||
273 | |||
274 | out: | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static void __exit wl1271_exit(void) | ||
279 | { | ||
280 | sdio_unregister_driver(&wl1271_sdio_driver); | ||
281 | |||
282 | wl1271_notice("unloaded"); | ||
283 | } | ||
284 | |||
285 | module_init(wl1271_init); | ||
286 | module_exit(wl1271_exit); | ||
287 | |||
288 | MODULE_LICENSE("GPL"); | ||
289 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||
290 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
291 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 053c84aceb49..5189b812f939 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -21,18 +21,69 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/irq.h> | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/spi/wl12xx.h> | ||
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | 30 | ||
30 | #include "wl1271.h" | 31 | #include "wl1271.h" |
31 | #include "wl12xx_80211.h" | 32 | #include "wl12xx_80211.h" |
32 | #include "wl1271_spi.h" | 33 | #include "wl1271_io.h" |
34 | |||
35 | #include "wl1271_reg.h" | ||
36 | |||
37 | #define WSPI_CMD_READ 0x40000000 | ||
38 | #define WSPI_CMD_WRITE 0x00000000 | ||
39 | #define WSPI_CMD_FIXED 0x20000000 | ||
40 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
41 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
42 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
43 | |||
44 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
45 | |||
46 | #define WSPI_INIT_CMD_START 0x00 | ||
47 | #define WSPI_INIT_CMD_TX 0x40 | ||
48 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
49 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
50 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
51 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
52 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
53 | #define WSPI_INIT_CMD_IOD 0x40 | ||
54 | #define WSPI_INIT_CMD_IP 0x20 | ||
55 | #define WSPI_INIT_CMD_CS 0x10 | ||
56 | #define WSPI_INIT_CMD_WS 0x08 | ||
57 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
58 | #define WSPI_INIT_CMD_END 0x01 | ||
59 | |||
60 | #define WSPI_INIT_CMD_LEN 8 | ||
61 | |||
62 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
63 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
64 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
65 | |||
66 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) | ||
67 | { | ||
68 | return wl->if_priv; | ||
69 | } | ||
33 | 70 | ||
71 | static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) | ||
72 | { | ||
73 | return &(wl_to_spi(wl)->dev); | ||
74 | } | ||
34 | 75 | ||
35 | void wl1271_spi_reset(struct wl1271 *wl) | 76 | static void wl1271_spi_disable_interrupts(struct wl1271 *wl) |
77 | { | ||
78 | disable_irq(wl->irq); | ||
79 | } | ||
80 | |||
81 | static void wl1271_spi_enable_interrupts(struct wl1271 *wl) | ||
82 | { | ||
83 | enable_irq(wl->irq); | ||
84 | } | ||
85 | |||
86 | static void wl1271_spi_reset(struct wl1271 *wl) | ||
36 | { | 87 | { |
37 | u8 *cmd; | 88 | u8 *cmd; |
38 | struct spi_transfer t; | 89 | struct spi_transfer t; |
@@ -53,12 +104,13 @@ void wl1271_spi_reset(struct wl1271 *wl) | |||
53 | t.len = WSPI_INIT_CMD_LEN; | 104 | t.len = WSPI_INIT_CMD_LEN; |
54 | spi_message_add_tail(&t, &m); | 105 | spi_message_add_tail(&t, &m); |
55 | 106 | ||
56 | spi_sync(wl->spi, &m); | 107 | spi_sync(wl_to_spi(wl), &m); |
108 | kfree(cmd); | ||
57 | 109 | ||
58 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 110 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
59 | } | 111 | } |
60 | 112 | ||
61 | void wl1271_spi_init(struct wl1271 *wl) | 113 | static void wl1271_spi_init(struct wl1271 *wl) |
62 | { | 114 | { |
63 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | 115 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; |
64 | struct spi_transfer t; | 116 | struct spi_transfer t; |
@@ -107,48 +159,25 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
107 | t.len = WSPI_INIT_CMD_LEN; | 159 | t.len = WSPI_INIT_CMD_LEN; |
108 | spi_message_add_tail(&t, &m); | 160 | spi_message_add_tail(&t, &m); |
109 | 161 | ||
110 | spi_sync(wl->spi, &m); | 162 | spi_sync(wl_to_spi(wl), &m); |
163 | kfree(cmd); | ||
111 | 164 | ||
112 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 165 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
113 | } | 166 | } |
114 | 167 | ||
115 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 168 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
116 | 169 | ||
117 | /* FIXME: Check busy words, removed due to SPI bug */ | 170 | static int wl1271_spi_read_busy(struct wl1271 *wl) |
118 | #if 0 | ||
119 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
120 | { | 171 | { |
121 | struct spi_transfer t[1]; | 172 | struct spi_transfer t[1]; |
122 | struct spi_message m; | 173 | struct spi_message m; |
123 | u32 *busy_buf; | 174 | u32 *busy_buf; |
124 | int num_busy_bytes = 0; | 175 | int num_busy_bytes = 0; |
125 | 176 | ||
126 | wl1271_info("spi read BUSY!"); | ||
127 | |||
128 | /* | ||
129 | * Look for the non-busy word in the read buffer, and if found, | ||
130 | * read in the remaining data into the buffer. | ||
131 | */ | ||
132 | busy_buf = (u32 *)buf; | ||
133 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
134 | num_busy_bytes += sizeof(u32); | ||
135 | if (*busy_buf & 0x1) { | ||
136 | spi_message_init(&m); | ||
137 | memset(t, 0, sizeof(t)); | ||
138 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
139 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
140 | t[0].len = num_busy_bytes; | ||
141 | spi_message_add_tail(&t[0], &m); | ||
142 | spi_sync(wl->spi, &m); | ||
143 | return; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /* | 177 | /* |
148 | * Read further busy words from SPI until a non-busy word is | 178 | * Read further busy words from SPI until a non-busy word is |
149 | * encountered, then read the data itself into the buffer. | 179 | * encountered, then read the data itself into the buffer. |
150 | */ | 180 | */ |
151 | wl1271_info("spi read BUSY-polling needed!"); | ||
152 | 181 | ||
153 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; | 182 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
154 | busy_buf = wl->buffer_busyword; | 183 | busy_buf = wl->buffer_busyword; |
@@ -158,28 +187,21 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
158 | memset(t, 0, sizeof(t)); | 187 | memset(t, 0, sizeof(t)); |
159 | t[0].rx_buf = busy_buf; | 188 | t[0].rx_buf = busy_buf; |
160 | t[0].len = sizeof(u32); | 189 | t[0].len = sizeof(u32); |
190 | t[0].cs_change = true; | ||
161 | spi_message_add_tail(&t[0], &m); | 191 | spi_message_add_tail(&t[0], &m); |
162 | spi_sync(wl->spi, &m); | 192 | spi_sync(wl_to_spi(wl), &m); |
163 | 193 | ||
164 | if (*busy_buf & 0x1) { | 194 | if (*busy_buf & 0x1) |
165 | spi_message_init(&m); | 195 | return 0; |
166 | memset(t, 0, sizeof(t)); | ||
167 | t[0].rx_buf = buf; | ||
168 | t[0].len = len; | ||
169 | spi_message_add_tail(&t[0], &m); | ||
170 | spi_sync(wl->spi, &m); | ||
171 | return; | ||
172 | } | ||
173 | } | 196 | } |
174 | 197 | ||
175 | /* The SPI bus is unresponsive, the read failed. */ | 198 | /* The SPI bus is unresponsive, the read failed. */ |
176 | memset(buf, 0, len); | ||
177 | wl1271_error("SPI read busy-word timeout!\n"); | 199 | wl1271_error("SPI read busy-word timeout!\n"); |
200 | return -ETIMEDOUT; | ||
178 | } | 201 | } |
179 | #endif | ||
180 | 202 | ||
181 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 203 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
182 | size_t len, bool fixed) | 204 | size_t len, bool fixed) |
183 | { | 205 | { |
184 | struct spi_transfer t[3]; | 206 | struct spi_transfer t[3]; |
185 | struct spi_message m; | 207 | struct spi_message m; |
@@ -202,28 +224,38 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
202 | 224 | ||
203 | t[0].tx_buf = cmd; | 225 | t[0].tx_buf = cmd; |
204 | t[0].len = 4; | 226 | t[0].len = 4; |
227 | t[0].cs_change = true; | ||
205 | spi_message_add_tail(&t[0], &m); | 228 | spi_message_add_tail(&t[0], &m); |
206 | 229 | ||
207 | /* Busy and non busy words read */ | 230 | /* Busy and non busy words read */ |
208 | t[1].rx_buf = busy_buf; | 231 | t[1].rx_buf = busy_buf; |
209 | t[1].len = WL1271_BUSY_WORD_LEN; | 232 | t[1].len = WL1271_BUSY_WORD_LEN; |
233 | t[1].cs_change = true; | ||
210 | spi_message_add_tail(&t[1], &m); | 234 | spi_message_add_tail(&t[1], &m); |
211 | 235 | ||
212 | t[2].rx_buf = buf; | 236 | spi_sync(wl_to_spi(wl), &m); |
213 | t[2].len = len; | ||
214 | spi_message_add_tail(&t[2], &m); | ||
215 | 237 | ||
216 | spi_sync(wl->spi, &m); | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
239 | wl1271_spi_read_busy(wl)) { | ||
240 | memset(buf, 0, len); | ||
241 | return; | ||
242 | } | ||
217 | 243 | ||
218 | /* FIXME: Check busy words, removed due to SPI bug */ | 244 | spi_message_init(&m); |
219 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | 245 | memset(t, 0, sizeof(t)); |
220 | wl1271_spi_read_busy(wl, buf, len); */ | 246 | |
247 | t[0].rx_buf = buf; | ||
248 | t[0].len = len; | ||
249 | t[0].cs_change = true; | ||
250 | spi_message_add_tail(&t[0], &m); | ||
251 | |||
252 | spi_sync(wl_to_spi(wl), &m); | ||
221 | 253 | ||
222 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 254 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
223 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 255 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
224 | } | 256 | } |
225 | 257 | ||
226 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | 258 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
227 | size_t len, bool fixed) | 259 | size_t len, bool fixed) |
228 | { | 260 | { |
229 | struct spi_transfer t[2]; | 261 | struct spi_transfer t[2]; |
@@ -251,8 +283,181 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
251 | t[1].len = len; | 283 | t[1].len = len; |
252 | spi_message_add_tail(&t[1], &m); | 284 | spi_message_add_tail(&t[1], &m); |
253 | 285 | ||
254 | spi_sync(wl->spi, &m); | 286 | spi_sync(wl_to_spi(wl), &m); |
255 | 287 | ||
256 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 288 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
257 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 289 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
258 | } | 290 | } |
291 | |||
292 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
293 | { | ||
294 | struct wl1271 *wl; | ||
295 | unsigned long flags; | ||
296 | |||
297 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
298 | |||
299 | wl = cookie; | ||
300 | |||
301 | /* complete the ELP completion */ | ||
302 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
303 | if (wl->elp_compl) { | ||
304 | complete(wl->elp_compl); | ||
305 | wl->elp_compl = NULL; | ||
306 | } | ||
307 | |||
308 | if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) | ||
309 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
310 | set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); | ||
311 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
312 | |||
313 | return IRQ_HANDLED; | ||
314 | } | ||
315 | |||
316 | static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) | ||
317 | { | ||
318 | if (wl->set_power) | ||
319 | wl->set_power(enable); | ||
320 | } | ||
321 | |||
322 | static struct wl1271_if_operations spi_ops = { | ||
323 | .read = wl1271_spi_raw_read, | ||
324 | .write = wl1271_spi_raw_write, | ||
325 | .reset = wl1271_spi_reset, | ||
326 | .init = wl1271_spi_init, | ||
327 | .power = wl1271_spi_set_power, | ||
328 | .dev = wl1271_spi_wl_to_dev, | ||
329 | .enable_irq = wl1271_spi_enable_interrupts, | ||
330 | .disable_irq = wl1271_spi_disable_interrupts | ||
331 | }; | ||
332 | |||
333 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
334 | { | ||
335 | struct wl12xx_platform_data *pdata; | ||
336 | struct ieee80211_hw *hw; | ||
337 | struct wl1271 *wl; | ||
338 | int ret; | ||
339 | |||
340 | pdata = spi->dev.platform_data; | ||
341 | if (!pdata) { | ||
342 | wl1271_error("no platform data"); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | |||
346 | hw = wl1271_alloc_hw(); | ||
347 | if (IS_ERR(hw)) | ||
348 | return PTR_ERR(hw); | ||
349 | |||
350 | wl = hw->priv; | ||
351 | |||
352 | dev_set_drvdata(&spi->dev, wl); | ||
353 | wl->if_priv = spi; | ||
354 | |||
355 | wl->if_ops = &spi_ops; | ||
356 | |||
357 | /* This is the only SPI value that we need to set here, the rest | ||
358 | * comes from the board-peripherals file */ | ||
359 | spi->bits_per_word = 32; | ||
360 | |||
361 | ret = spi_setup(spi); | ||
362 | if (ret < 0) { | ||
363 | wl1271_error("spi_setup failed"); | ||
364 | goto out_free; | ||
365 | } | ||
366 | |||
367 | wl->set_power = pdata->set_power; | ||
368 | if (!wl->set_power) { | ||
369 | wl1271_error("set power function missing in platform data"); | ||
370 | ret = -ENODEV; | ||
371 | goto out_free; | ||
372 | } | ||
373 | |||
374 | wl->irq = spi->irq; | ||
375 | if (wl->irq < 0) { | ||
376 | wl1271_error("irq missing in platform data"); | ||
377 | ret = -ENODEV; | ||
378 | goto out_free; | ||
379 | } | ||
380 | |||
381 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
382 | if (ret < 0) { | ||
383 | wl1271_error("request_irq() failed: %d", ret); | ||
384 | goto out_free; | ||
385 | } | ||
386 | |||
387 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
388 | |||
389 | disable_irq(wl->irq); | ||
390 | |||
391 | ret = wl1271_init_ieee80211(wl); | ||
392 | if (ret) | ||
393 | goto out_irq; | ||
394 | |||
395 | ret = wl1271_register_hw(wl); | ||
396 | if (ret) | ||
397 | goto out_irq; | ||
398 | |||
399 | wl1271_notice("initialized"); | ||
400 | |||
401 | return 0; | ||
402 | |||
403 | out_irq: | ||
404 | free_irq(wl->irq, wl); | ||
405 | |||
406 | out_free: | ||
407 | wl1271_free_hw(wl); | ||
408 | |||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
413 | { | ||
414 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
415 | |||
416 | free_irq(wl->irq, wl); | ||
417 | |||
418 | wl1271_unregister_hw(wl); | ||
419 | wl1271_free_hw(wl); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | |||
425 | static struct spi_driver wl1271_spi_driver = { | ||
426 | .driver = { | ||
427 | .name = "wl1271_spi", | ||
428 | .bus = &spi_bus_type, | ||
429 | .owner = THIS_MODULE, | ||
430 | }, | ||
431 | |||
432 | .probe = wl1271_probe, | ||
433 | .remove = __devexit_p(wl1271_remove), | ||
434 | }; | ||
435 | |||
436 | static int __init wl1271_init(void) | ||
437 | { | ||
438 | int ret; | ||
439 | |||
440 | ret = spi_register_driver(&wl1271_spi_driver); | ||
441 | if (ret < 0) { | ||
442 | wl1271_error("failed to register spi driver: %d", ret); | ||
443 | goto out; | ||
444 | } | ||
445 | |||
446 | out: | ||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | static void __exit wl1271_exit(void) | ||
451 | { | ||
452 | spi_unregister_driver(&wl1271_spi_driver); | ||
453 | |||
454 | wl1271_notice("unloaded"); | ||
455 | } | ||
456 | |||
457 | module_init(wl1271_init); | ||
458 | module_exit(wl1271_exit); | ||
459 | |||
460 | MODULE_LICENSE("GPL"); | ||
461 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||
462 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
463 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h deleted file mode 100644 index a803596dad4a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2009 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1271_SPI_H__ | ||
26 | #define __WL1271_SPI_H__ | ||
27 | |||
28 | #include "wl1271_reg.h" | ||
29 | |||
30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | ||
31 | |||
32 | #define HW_PARTITION_REGISTERS_ADDR 0x1ffc0 | ||
33 | #define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) | ||
34 | #define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) | ||
35 | #define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) | ||
36 | #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) | ||
37 | #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) | ||
38 | #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) | ||
39 | #define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) | ||
40 | |||
41 | #define HW_ACCESS_REGISTER_SIZE 4 | ||
42 | |||
43 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | ||
44 | |||
45 | #define WSPI_CMD_READ 0x40000000 | ||
46 | #define WSPI_CMD_WRITE 0x00000000 | ||
47 | #define WSPI_CMD_FIXED 0x20000000 | ||
48 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
49 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
50 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
51 | |||
52 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
53 | |||
54 | #define WSPI_INIT_CMD_START 0x00 | ||
55 | #define WSPI_INIT_CMD_TX 0x40 | ||
56 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
57 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
58 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
59 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
60 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
61 | #define WSPI_INIT_CMD_IOD 0x40 | ||
62 | #define WSPI_INIT_CMD_IP 0x20 | ||
63 | #define WSPI_INIT_CMD_CS 0x10 | ||
64 | #define WSPI_INIT_CMD_WS 0x08 | ||
65 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
66 | #define WSPI_INIT_CMD_END 0x01 | ||
67 | |||
68 | #define WSPI_INIT_CMD_LEN 8 | ||
69 | |||
70 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
71 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
72 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
73 | |||
74 | #define OCP_CMD_LOOP 32 | ||
75 | |||
76 | #define OCP_CMD_WRITE 0x1 | ||
77 | #define OCP_CMD_READ 0x2 | ||
78 | |||
79 | #define OCP_READY_MASK BIT(18) | ||
80 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
81 | |||
82 | #define OCP_STATUS_NO_RESP 0x00000 | ||
83 | #define OCP_STATUS_OK 0x10000 | ||
84 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
85 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
86 | |||
87 | /* Raw target IO, address is not translated */ | ||
88 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
89 | size_t len, bool fixed); | ||
90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
91 | size_t len, bool fixed); | ||
92 | |||
93 | /* INIT and RESET words */ | ||
94 | void wl1271_spi_reset(struct wl1271 *wl); | ||
95 | void wl1271_spi_init(struct wl1271 *wl); | ||
96 | #endif /* __WL1271_SPI_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 5c1c4f565fd8..554deb4d024e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <net/genetlink.h> | 26 | #include <net/genetlink.h> |
27 | 27 | ||
28 | #include "wl1271.h" | 28 | #include "wl1271.h" |
29 | #include "wl1271_spi.h" | ||
30 | #include "wl1271_acx.h" | 29 | #include "wl1271_acx.h" |
31 | 30 | ||
32 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | 31 | #define WL1271_TM_MAX_DATA_LENGTH 1024 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 811e739d05bf..62db79508ddf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_io.h" | 28 | #include "wl1271_io.h" |
30 | #include "wl1271_reg.h" | 29 | #include "wl1271_reg.h" |
31 | #include "wl1271_ps.h" | 30 | #include "wl1271_ps.h" |
@@ -47,7 +46,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
47 | { | 46 | { |
48 | struct wl1271_tx_hw_descr *desc; | 47 | struct wl1271_tx_hw_descr *desc; |
49 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 48 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
50 | u32 total_blocks, excluded; | 49 | u32 total_blocks; |
51 | int id, ret = -EBUSY; | 50 | int id, ret = -EBUSY; |
52 | 51 | ||
53 | /* allocate free identifier for the packet */ | 52 | /* allocate free identifier for the packet */ |
@@ -57,12 +56,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
57 | 56 | ||
58 | /* approximate the number of blocks required for this packet | 57 | /* approximate the number of blocks required for this packet |
59 | in the firmware */ | 58 | in the firmware */ |
60 | /* FIXME: try to figure out what is done here and make it cleaner */ | 59 | total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; |
61 | total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV; | 60 | total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; |
62 | excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34; | ||
63 | total_blocks += (excluded > 252) ? 2 : 1; | ||
64 | total_blocks += TX_HW_BLOCK_SPARE; | ||
65 | |||
66 | if (total_blocks <= wl->tx_blocks_available) { | 61 | if (total_blocks <= wl->tx_blocks_available) { |
67 | desc = (struct wl1271_tx_hw_descr *)skb_push( | 62 | desc = (struct wl1271_tx_hw_descr *)skb_push( |
68 | skb, total_len - skb->len); | 63 | skb, total_len - skb->len); |
@@ -87,8 +82,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
87 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 82 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, |
88 | u32 extra, struct ieee80211_tx_info *control) | 83 | u32 extra, struct ieee80211_tx_info *control) |
89 | { | 84 | { |
85 | struct timespec ts; | ||
90 | struct wl1271_tx_hw_descr *desc; | 86 | struct wl1271_tx_hw_descr *desc; |
91 | int pad, ac; | 87 | int pad, ac; |
88 | s64 hosttime; | ||
92 | u16 tx_attr; | 89 | u16 tx_attr; |
93 | 90 | ||
94 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 91 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
@@ -102,8 +99,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
102 | } | 99 | } |
103 | 100 | ||
104 | /* configure packet life time */ | 101 | /* configure packet life time */ |
105 | desc->start_time = cpu_to_le32(jiffies_to_usecs(jiffies) - | 102 | getnstimeofday(&ts); |
106 | wl->time_offset); | 103 | hosttime = (timespec_to_ns(&ts) >> 10); |
104 | desc->start_time = cpu_to_le32(hosttime - wl->time_offset); | ||
107 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); | 105 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); |
108 | 106 | ||
109 | /* configure the tx attributes */ | 107 | /* configure the tx attributes */ |
@@ -170,7 +168,6 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | |||
170 | 168 | ||
171 | /* write packet new counter into the write access register */ | 169 | /* write packet new counter into the write access register */ |
172 | wl->tx_packets_count++; | 170 | wl->tx_packets_count++; |
173 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | ||
174 | 171 | ||
175 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 172 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | 173 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", |
@@ -223,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
223 | return ret; | 220 | return ret; |
224 | } | 221 | } |
225 | 222 | ||
226 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 223 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
227 | { | 224 | { |
228 | struct ieee80211_supported_band *band; | 225 | struct ieee80211_supported_band *band; |
229 | u32 enabled_rates = 0; | 226 | u32 enabled_rates = 0; |
@@ -245,6 +242,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
245 | struct sk_buff *skb; | 242 | struct sk_buff *skb; |
246 | bool woken_up = false; | 243 | bool woken_up = false; |
247 | u32 sta_rates = 0; | 244 | u32 sta_rates = 0; |
245 | u32 prev_tx_packets_count; | ||
248 | int ret; | 246 | int ret; |
249 | 247 | ||
250 | /* check if the rates supported by the AP have changed */ | 248 | /* check if the rates supported by the AP have changed */ |
@@ -261,6 +259,8 @@ void wl1271_tx_work(struct work_struct *work) | |||
261 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 259 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
262 | goto out; | 260 | goto out; |
263 | 261 | ||
262 | prev_tx_packets_count = wl->tx_packets_count; | ||
263 | |||
264 | /* if rates have changed, re-configure the rate policy */ | 264 | /* if rates have changed, re-configure the rate policy */ |
265 | if (unlikely(sta_rates)) { | 265 | if (unlikely(sta_rates)) { |
266 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | 266 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); |
@@ -271,31 +271,26 @@ void wl1271_tx_work(struct work_struct *work) | |||
271 | if (!woken_up) { | 271 | if (!woken_up) { |
272 | ret = wl1271_ps_elp_wakeup(wl, false); | 272 | ret = wl1271_ps_elp_wakeup(wl, false); |
273 | if (ret < 0) | 273 | if (ret < 0) |
274 | goto out; | 274 | goto out_ack; |
275 | woken_up = true; | 275 | woken_up = true; |
276 | } | 276 | } |
277 | 277 | ||
278 | ret = wl1271_tx_frame(wl, skb); | 278 | ret = wl1271_tx_frame(wl, skb); |
279 | if (ret == -EBUSY) { | 279 | if (ret == -EBUSY) { |
280 | /* firmware buffer is full, stop queues */ | 280 | /* firmware buffer is full, lets stop transmitting. */ |
281 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | ||
282 | "stop queues"); | ||
283 | ieee80211_stop_queues(wl->hw); | ||
284 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
285 | skb_queue_head(&wl->tx_queue, skb); | 281 | skb_queue_head(&wl->tx_queue, skb); |
286 | goto out; | 282 | goto out_ack; |
287 | } else if (ret < 0) { | 283 | } else if (ret < 0) { |
288 | dev_kfree_skb(skb); | 284 | dev_kfree_skb(skb); |
289 | goto out; | 285 | goto out_ack; |
290 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, | ||
291 | &wl->flags)) { | ||
292 | /* firmware buffer has space, restart queues */ | ||
293 | wl1271_debug(DEBUG_TX, | ||
294 | "complete_packet: waking queues"); | ||
295 | ieee80211_wake_queues(wl->hw); | ||
296 | } | 286 | } |
297 | } | 287 | } |
298 | 288 | ||
289 | out_ack: | ||
290 | /* interrupt the firmware with the new packets */ | ||
291 | if (prev_tx_packets_count != wl->tx_packets_count) | ||
292 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | ||
293 | |||
299 | out: | 294 | out: |
300 | if (woken_up) | 295 | if (woken_up) |
301 | wl1271_ps_elp_sleep(wl); | 296 | wl1271_ps_elp_sleep(wl); |
@@ -308,11 +303,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
308 | { | 303 | { |
309 | struct ieee80211_tx_info *info; | 304 | struct ieee80211_tx_info *info; |
310 | struct sk_buff *skb; | 305 | struct sk_buff *skb; |
311 | u16 seq; | ||
312 | int id = result->id; | 306 | int id = result->id; |
307 | int rate = -1; | ||
308 | u8 retries = 0; | ||
313 | 309 | ||
314 | /* check for id legality */ | 310 | /* check for id legality */ |
315 | if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { | 311 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
316 | wl1271_warning("TX result illegal id: %d", id); | 312 | wl1271_warning("TX result illegal id: %d", id); |
317 | return; | 313 | return; |
318 | } | 314 | } |
@@ -320,31 +316,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
320 | skb = wl->tx_frames[id]; | 316 | skb = wl->tx_frames[id]; |
321 | info = IEEE80211_SKB_CB(skb); | 317 | info = IEEE80211_SKB_CB(skb); |
322 | 318 | ||
323 | /* update packet status */ | 319 | /* update the TX status info */ |
324 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 320 | if (result->status == TX_SUCCESS) { |
325 | if (result->status == TX_SUCCESS) | 321 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
326 | info->flags |= IEEE80211_TX_STAT_ACK; | 322 | info->flags |= IEEE80211_TX_STAT_ACK; |
327 | if (result->status & TX_RETRY_EXCEEDED) { | 323 | rate = wl1271_rate_to_idx(wl, result->rate_class_index); |
328 | /* FIXME */ | 324 | retries = result->ack_failures; |
329 | /* info->status.excessive_retries = 1; */ | 325 | } else if (result->status == TX_RETRY_EXCEEDED) { |
330 | wl->stats.excessive_retries++; | 326 | wl->stats.excessive_retries++; |
331 | } | 327 | retries = result->ack_failures; |
332 | } | 328 | } |
333 | 329 | ||
334 | /* FIXME */ | 330 | info->status.rates[0].idx = rate; |
335 | /* info->status.retry_count = result->ack_failures; */ | 331 | info->status.rates[0].count = retries; |
332 | info->status.rates[0].flags = 0; | ||
333 | info->status.ack_signal = -1; | ||
334 | |||
336 | wl->stats.retry_count += result->ack_failures; | 335 | wl->stats.retry_count += result->ack_failures; |
337 | 336 | ||
338 | /* update security sequence number */ | 337 | /* update security sequence number */ |
339 | seq = wl->tx_security_seq_16 + | 338 | wl->tx_security_seq += (result->lsb_security_sequence_number - |
340 | (result->lsb_security_sequence_number - | 339 | wl->tx_security_last_seq); |
341 | wl->tx_security_last_seq); | ||
342 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 340 | wl->tx_security_last_seq = result->lsb_security_sequence_number; |
343 | 341 | ||
344 | if (seq < wl->tx_security_seq_16) | ||
345 | wl->tx_security_seq_32++; | ||
346 | wl->tx_security_seq_16 = seq; | ||
347 | |||
348 | /* remove private header from packet */ | 342 | /* remove private header from packet */ |
349 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 343 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
350 | 344 | ||
@@ -367,23 +361,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
367 | } | 361 | } |
368 | 362 | ||
369 | /* Called upon reception of a TX complete interrupt */ | 363 | /* Called upon reception of a TX complete interrupt */ |
370 | void wl1271_tx_complete(struct wl1271 *wl, u32 count) | 364 | void wl1271_tx_complete(struct wl1271 *wl) |
371 | { | 365 | { |
372 | struct wl1271_acx_mem_map *memmap = | 366 | struct wl1271_acx_mem_map *memmap = |
373 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 367 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
368 | u32 count, fw_counter; | ||
374 | u32 i; | 369 | u32 i; |
375 | 370 | ||
376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
377 | |||
378 | /* read the tx results from the chipset */ | 371 | /* read the tx results from the chipset */ |
379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 372 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 373 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
374 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | ||
375 | |||
376 | /* write host counter to chipset (to ack) */ | ||
377 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | ||
378 | offsetof(struct wl1271_tx_hw_res_if, | ||
379 | tx_result_host_counter), fw_counter); | ||
380 | |||
381 | count = fw_counter - wl->tx_results_count; | ||
382 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
381 | 383 | ||
382 | /* verify that the result buffer is not getting overrun */ | 384 | /* verify that the result buffer is not getting overrun */ |
383 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 385 | if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) |
384 | wl1271_warning("TX result overflow from chipset: %d", count); | 386 | wl1271_warning("TX result overflow from chipset: %d", count); |
385 | count = TX_HW_RESULT_QUEUE_LEN; | ||
386 | } | ||
387 | 387 | ||
388 | /* process the results */ | 388 | /* process the results */ |
389 | for (i = 0; i < count; i++) { | 389 | for (i = 0; i < count; i++) { |
@@ -397,11 +397,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
397 | wl->tx_results_count++; | 397 | wl->tx_results_count++; |
398 | } | 398 | } |
399 | 399 | ||
400 | /* write host counter to chipset (to ack) */ | 400 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 401 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
402 | offsetof(struct wl1271_tx_hw_res_if, | 402 | unsigned long flags; |
403 | tx_result_host_counter), | 403 | |
404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 404 | /* firmware buffer has space, restart queues */ |
405 | wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); | ||
406 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
407 | ieee80211_wake_queues(wl->hw); | ||
408 | clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
409 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
410 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
411 | } | ||
405 | } | 412 | } |
406 | 413 | ||
407 | /* caller must hold wl->mutex */ | 414 | /* caller must hold wl->mutex */ |
@@ -409,31 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
409 | { | 416 | { |
410 | int i; | 417 | int i; |
411 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
412 | struct ieee80211_tx_info *info; | ||
413 | 419 | ||
414 | /* TX failure */ | 420 | /* TX failure */ |
415 | /* control->flags = 0; FIXME */ | 421 | /* control->flags = 0; FIXME */ |
416 | 422 | ||
417 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 423 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
418 | info = IEEE80211_SKB_CB(skb); | ||
419 | |||
420 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); | 424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); |
421 | |||
422 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
423 | continue; | ||
424 | |||
425 | ieee80211_tx_status(wl->hw, skb); | 425 | ieee80211_tx_status(wl->hw, skb); |
426 | } | 426 | } |
427 | 427 | ||
428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
429 | if (wl->tx_frames[i] != NULL) { | 429 | if (wl->tx_frames[i] != NULL) { |
430 | skb = wl->tx_frames[i]; | 430 | skb = wl->tx_frames[i]; |
431 | info = IEEE80211_SKB_CB(skb); | ||
432 | |||
433 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
434 | continue; | ||
435 | |||
436 | ieee80211_tx_status(wl->hw, skb); | ||
437 | wl->tx_frames[i] = NULL; | 431 | wl->tx_frames[i] = NULL; |
432 | ieee80211_tx_status(wl->hw, skb); | ||
438 | } | 433 | } |
439 | } | 434 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 17e405a09caa..3b8b7ac253fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #define __WL1271_TX_H__ | 26 | #define __WL1271_TX_H__ |
27 | 27 | ||
28 | #define TX_HW_BLOCK_SPARE 2 | 28 | #define TX_HW_BLOCK_SPARE 2 |
29 | #define TX_HW_BLOCK_SHIFT_DIV 8 | 29 | #define TX_HW_BLOCK_SIZE 252 |
30 | 30 | ||
31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 | 31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 |
32 | /* The chipset reference driver states, that the "aid" value 1 | 32 | /* The chipset reference driver states, that the "aid" value 1 |
@@ -125,9 +125,6 @@ struct wl1271_tx_hw_res_if { | |||
125 | 125 | ||
126 | static inline int wl1271_tx_get_queue(int queue) | 126 | static inline int wl1271_tx_get_queue(int queue) |
127 | { | 127 | { |
128 | /* FIXME: use best effort until WMM is enabled */ | ||
129 | return CONF_TX_AC_BE; | ||
130 | |||
131 | switch (queue) { | 128 | switch (queue) { |
132 | case 0: | 129 | case 0: |
133 | return CONF_TX_AC_VO; | 130 | return CONF_TX_AC_VO; |
@@ -160,7 +157,9 @@ static inline int wl1271_tx_ac_to_tid(int ac) | |||
160 | } | 157 | } |
161 | 158 | ||
162 | void wl1271_tx_work(struct work_struct *work); | 159 | void wl1271_tx_work(struct work_struct *work); |
163 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); | 160 | void wl1271_tx_complete(struct wl1271 *wl); |
164 | void wl1271_tx_flush(struct wl1271 *wl); | 161 | void wl1271_tx_flush(struct wl1271 *wl); |
162 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
163 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | ||
165 | 164 | ||
166 | #endif | 165 | #endif |