diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx')
29 files changed, 1646 insertions, 1042 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 28a808674080..acb334184d70 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -496,7 +496,8 @@ int wl1251_boot(struct wl1251 *wl) | |||
496 | /* 2. start processing NVS file */ | 496 | /* 2. start processing NVS file */ |
497 | if (wl->use_eeprom) { | 497 | if (wl->use_eeprom) { |
498 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); | 498 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); |
499 | msleep(4000); | 499 | /* Wait for EEPROM NVS burst read to complete */ |
500 | msleep(40); | ||
500 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | 501 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); |
501 | } else { | 502 | } else { |
502 | ret = wl1251_boot_upload_nvs(wl); | 503 | 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 24ae6a360ac8..0155653b7105 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -146,8 +146,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) | |||
146 | u32 elp_reg; | 146 | u32 elp_reg; |
147 | 147 | ||
148 | elp_reg = ELPCTRL_WAKE_UP; | 148 | elp_reg = ELPCTRL_WAKE_UP; |
149 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | 149 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); |
150 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 150 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
151 | 151 | ||
152 | if (!(elp_reg & ELPCTRL_WLAN_READY)) | 152 | if (!(elp_reg & ELPCTRL_WLAN_READY)) |
153 | wl1251_warning("WLAN not ready"); | 153 | wl1251_warning("WLAN not ready"); |
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_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 9423f22bdced..2051ef06e9ec 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -20,20 +20,11 @@ | |||
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> | ||
29 | 26 | ||
30 | #include "wl1251.h" | 27 | #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 | 28 | ||
38 | #ifndef SDIO_VENDOR_ID_TI | 29 | #ifndef SDIO_VENDOR_ID_TI |
39 | #define SDIO_VENDOR_ID_TI 0x104c | 30 | #define SDIO_VENDOR_ID_TI 0x104c |
@@ -65,7 +56,8 @@ static const struct sdio_device_id wl1251_devices[] = { | |||
65 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); | 56 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); |
66 | 57 | ||
67 | 58 | ||
68 | void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | 59 | static void wl1251_sdio_read(struct wl1251 *wl, int addr, |
60 | void *buf, size_t len) | ||
69 | { | 61 | { |
70 | int ret; | 62 | int ret; |
71 | struct sdio_func *func = wl_to_func(wl); | 63 | struct sdio_func *func = wl_to_func(wl); |
@@ -77,7 +69,8 @@ void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
77 | sdio_release_host(func); | 69 | sdio_release_host(func); |
78 | } | 70 | } |
79 | 71 | ||
80 | void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | 72 | static void wl1251_sdio_write(struct wl1251 *wl, int addr, |
73 | void *buf, size_t len) | ||
81 | { | 74 | { |
82 | int ret; | 75 | int ret; |
83 | struct sdio_func *func = wl_to_func(wl); | 76 | struct sdio_func *func = wl_to_func(wl); |
@@ -89,7 +82,33 @@ void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
89 | sdio_release_host(func); | 82 | sdio_release_host(func); |
90 | } | 83 | } |
91 | 84 | ||
92 | void wl1251_sdio_reset(struct wl1251 *wl) | 85 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) |
86 | { | ||
87 | int ret = 0; | ||
88 | struct sdio_func *func = wl_to_func(wl); | ||
89 | |||
90 | sdio_claim_host(func); | ||
91 | *val = sdio_readb(func, addr, &ret); | ||
92 | sdio_release_host(func); | ||
93 | |||
94 | if (ret) | ||
95 | wl1251_error("sdio_readb failed (%d)", ret); | ||
96 | } | ||
97 | |||
98 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
99 | { | ||
100 | int ret = 0; | ||
101 | struct sdio_func *func = wl_to_func(wl); | ||
102 | |||
103 | sdio_claim_host(func); | ||
104 | sdio_writeb(func, val, addr, &ret); | ||
105 | sdio_release_host(func); | ||
106 | |||
107 | if (ret) | ||
108 | wl1251_error("sdio_writeb failed (%d)", ret); | ||
109 | } | ||
110 | |||
111 | static void wl1251_sdio_reset(struct wl1251 *wl) | ||
93 | { | 112 | { |
94 | } | 113 | } |
95 | 114 | ||
@@ -111,19 +130,22 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) | |||
111 | sdio_release_host(func); | 130 | sdio_release_host(func); |
112 | } | 131 | } |
113 | 132 | ||
114 | void wl1251_sdio_set_power(bool enable) | 133 | static void wl1251_sdio_set_power(bool enable) |
115 | { | 134 | { |
116 | } | 135 | } |
117 | 136 | ||
118 | struct wl1251_if_operations wl1251_sdio_ops = { | 137 | static const struct wl1251_if_operations wl1251_sdio_ops = { |
119 | .read = wl1251_sdio_read, | 138 | .read = wl1251_sdio_read, |
120 | .write = wl1251_sdio_write, | 139 | .write = wl1251_sdio_write, |
140 | .write_elp = wl1251_sdio_write_elp, | ||
141 | .read_elp = wl1251_sdio_read_elp, | ||
121 | .reset = wl1251_sdio_reset, | 142 | .reset = wl1251_sdio_reset, |
122 | .enable_irq = wl1251_sdio_enable_irq, | 143 | .enable_irq = wl1251_sdio_enable_irq, |
123 | .disable_irq = wl1251_sdio_disable_irq, | 144 | .disable_irq = wl1251_sdio_disable_irq, |
124 | }; | 145 | }; |
125 | 146 | ||
126 | int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | 147 | static int wl1251_sdio_probe(struct sdio_func *func, |
148 | const struct sdio_device_id *id) | ||
127 | { | 149 | { |
128 | int ret; | 150 | int ret; |
129 | struct wl1251 *wl; | 151 | struct wl1251 *wl; |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 97ea5096bc8c..8f11506f8310 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -53,6 +53,8 @@ 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), | ||
56 | DEBUG_ALL = ~0, | 58 | DEBUG_ALL = ~0, |
57 | }; | 59 | }; |
58 | 60 | ||
@@ -110,6 +112,9 @@ enum { | |||
110 | #define WL1271_FW_NAME "wl1271-fw.bin" | 112 | #define WL1271_FW_NAME "wl1271-fw.bin" |
111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | 114 | ||
115 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | ||
116 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | ||
117 | |||
113 | /* NVS data structure */ | 118 | /* NVS data structure */ |
114 | #define WL1271_NVS_SECTION_SIZE 468 | 119 | #define WL1271_NVS_SECTION_SIZE 468 |
115 | 120 | ||
@@ -334,11 +339,27 @@ struct wl1271_scan { | |||
334 | u8 probe_requests; | 339 | u8 probe_requests; |
335 | }; | 340 | }; |
336 | 341 | ||
342 | struct wl1271_if_operations { | ||
343 | void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
344 | bool fixed); | ||
345 | void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
346 | bool fixed); | ||
347 | void (*reset)(struct wl1271 *wl); | ||
348 | void (*init)(struct wl1271 *wl); | ||
349 | void (*power)(struct wl1271 *wl, bool enable); | ||
350 | struct device* (*dev)(struct wl1271 *wl); | ||
351 | void (*enable_irq)(struct wl1271 *wl); | ||
352 | void (*disable_irq)(struct wl1271 *wl); | ||
353 | }; | ||
354 | |||
337 | struct wl1271 { | 355 | struct wl1271 { |
356 | struct platform_device *plat_dev; | ||
338 | struct ieee80211_hw *hw; | 357 | struct ieee80211_hw *hw; |
339 | bool mac80211_registered; | 358 | bool mac80211_registered; |
340 | 359 | ||
341 | struct spi_device *spi; | 360 | void *if_priv; |
361 | |||
362 | struct wl1271_if_operations *if_ops; | ||
342 | 363 | ||
343 | void (*set_power)(bool enable); | 364 | void (*set_power)(bool enable); |
344 | int irq; | 365 | int irq; |
@@ -357,6 +378,8 @@ struct wl1271 { | |||
357 | #define WL1271_FLAG_IN_ELP (6) | 378 | #define WL1271_FLAG_IN_ELP (6) |
358 | #define WL1271_FLAG_PSM (7) | 379 | #define WL1271_FLAG_PSM (7) |
359 | #define WL1271_FLAG_PSM_REQUESTED (8) | 380 | #define WL1271_FLAG_PSM_REQUESTED (8) |
381 | #define WL1271_FLAG_IRQ_PENDING (9) | ||
382 | #define WL1271_FLAG_IRQ_RUNNING (10) | ||
360 | unsigned long flags; | 383 | unsigned long flags; |
361 | 384 | ||
362 | struct wl1271_partition_set part; | 385 | struct wl1271_partition_set part; |
@@ -382,13 +405,13 @@ struct wl1271 { | |||
382 | /* Accounting for allocated / available TX blocks on HW */ | 405 | /* Accounting for allocated / available TX blocks on HW */ |
383 | u32 tx_blocks_freed[NUM_TX_QUEUES]; | 406 | u32 tx_blocks_freed[NUM_TX_QUEUES]; |
384 | u32 tx_blocks_available; | 407 | u32 tx_blocks_available; |
385 | u8 tx_results_count; | 408 | u32 tx_results_count; |
386 | 409 | ||
387 | /* Transmitted TX packets counter for chipset interface */ | 410 | /* Transmitted TX packets counter for chipset interface */ |
388 | int tx_packets_count; | 411 | u32 tx_packets_count; |
389 | 412 | ||
390 | /* Time-offset between host and chipset clocks */ | 413 | /* Time-offset between host and chipset clocks */ |
391 | int time_offset; | 414 | s64 time_offset; |
392 | 415 | ||
393 | /* Session counter for the chipset */ | 416 | /* Session counter for the chipset */ |
394 | int session_counter; | 417 | int session_counter; |
@@ -403,8 +426,7 @@ struct wl1271 { | |||
403 | 426 | ||
404 | /* Security sequence number counters */ | 427 | /* Security sequence number counters */ |
405 | u8 tx_security_last_seq; | 428 | u8 tx_security_last_seq; |
406 | u16 tx_security_seq_16; | 429 | s64 tx_security_seq; |
407 | u32 tx_security_seq_32; | ||
408 | 430 | ||
409 | /* FW Rx counter */ | 431 | /* FW Rx counter */ |
410 | u32 rx_counter; | 432 | u32 rx_counter; |
@@ -438,6 +460,7 @@ struct wl1271 { | |||
438 | /* Default key (for WEP) */ | 460 | /* Default key (for WEP) */ |
439 | u32 default_key; | 461 | u32 default_key; |
440 | 462 | ||
463 | unsigned int filters; | ||
441 | unsigned int rx_config; | 464 | unsigned int rx_config; |
442 | unsigned int rx_filter; | 465 | unsigned int rx_filter; |
443 | 466 | ||
@@ -465,6 +488,8 @@ struct wl1271 { | |||
465 | /* Current chipset configuration */ | 488 | /* Current chipset configuration */ |
466 | struct conf_drv_settings conf; | 489 | struct conf_drv_settings conf; |
467 | 490 | ||
491 | bool sg_enabled; | ||
492 | |||
468 | struct list_head list; | 493 | struct list_head list; |
469 | }; | 494 | }; |
470 | 495 | ||
@@ -477,7 +502,8 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
477 | 502 | ||
478 | #define WL1271_DEFAULT_POWER_LEVEL 0 | 503 | #define WL1271_DEFAULT_POWER_LEVEL 0 |
479 | 504 | ||
480 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 505 | #define WL1271_TX_QUEUE_LOW_WATERMARK 10 |
506 | #define WL1271_TX_QUEUE_HIGH_WATERMARK 25 | ||
481 | 507 | ||
482 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power | 508 | /* 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 */ | 509 | 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 60f10dce4800..7e337cea9905 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include "wl1271.h" | 31 | #include "wl1271.h" |
32 | #include "wl12xx_80211.h" | 32 | #include "wl12xx_80211.h" |
33 | #include "wl1271_reg.h" | 33 | #include "wl1271_reg.h" |
34 | #include "wl1271_spi.h" | ||
35 | #include "wl1271_ps.h" | 34 | #include "wl1271_ps.h" |
36 | 35 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) | 36 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) |
@@ -136,12 +135,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
136 | goto out; | 135 | goto out; |
137 | } | 136 | } |
138 | 137 | ||
139 | /* | 138 | acx->current_tx_power = power * 10; |
140 | * FIXME: This is a workaround needed while we don't the correct | ||
141 | * calibration, to avoid distortions | ||
142 | */ | ||
143 | /* acx->current_tx_power = power * 10; */ | ||
144 | acx->current_tx_power = 120; | ||
145 | 139 | ||
146 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | 140 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
147 | if (ret < 0) { | 141 | if (ret < 0) { |
@@ -540,7 +534,7 @@ out: | |||
540 | } | 534 | } |
541 | 535 | ||
542 | 536 | ||
543 | int wl1271_acx_sg_enable(struct wl1271 *wl) | 537 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable) |
544 | { | 538 | { |
545 | struct acx_bt_wlan_coex *pta; | 539 | struct acx_bt_wlan_coex *pta; |
546 | int ret; | 540 | int ret; |
@@ -553,7 +547,10 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) | |||
553 | goto out; | 547 | goto out; |
554 | } | 548 | } |
555 | 549 | ||
556 | pta->enable = SG_ENABLE; | 550 | if (enable) |
551 | pta->enable = wl->conf.sg.state; | ||
552 | else | ||
553 | pta->enable = CONF_SG_DISABLE; | ||
557 | 554 | ||
558 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); | 555 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); |
559 | if (ret < 0) { | 556 | if (ret < 0) { |
@@ -570,7 +567,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
570 | { | 567 | { |
571 | struct acx_bt_wlan_coex_param *param; | 568 | struct acx_bt_wlan_coex_param *param; |
572 | struct conf_sg_settings *c = &wl->conf.sg; | 569 | struct conf_sg_settings *c = &wl->conf.sg; |
573 | int ret; | 570 | int i, ret; |
574 | 571 | ||
575 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 572 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); |
576 | 573 | ||
@@ -581,19 +578,9 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
581 | } | 578 | } |
582 | 579 | ||
583 | /* BT-WLAN coext parameters */ | 580 | /* BT-WLAN coext parameters */ |
584 | param->per_threshold = cpu_to_le32(c->per_threshold); | 581 | for (i = 0; i < CONF_SG_PARAMS_MAX; i++) |
585 | param->max_scan_compensation_time = | 582 | param->params[i] = c->params[i]; |
586 | cpu_to_le32(c->max_scan_compensation_time); | 583 | param->param_idx = CONF_SG_PARAMS_ALL; |
587 | param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); | ||
588 | param->load_ratio = c->load_ratio; | ||
589 | param->auto_ps_mode = c->auto_ps_mode; | ||
590 | param->probe_req_compensation = c->probe_req_compensation; | ||
591 | param->scan_window_compensation = c->scan_window_compensation; | ||
592 | param->antenna_config = c->antenna_config; | ||
593 | param->beacon_miss_threshold = c->beacon_miss_threshold; | ||
594 | param->rate_adaptation_threshold = | ||
595 | cpu_to_le32(c->rate_adaptation_threshold); | ||
596 | param->rate_adaptation_snr = c->rate_adaptation_snr; | ||
597 | 584 | ||
598 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 585 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
599 | if (ret < 0) { | 586 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index aeccc98581eb..8e5870fa9609 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 { |
@@ -1059,7 +1005,7 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | |||
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1005 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1006 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1007 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); |
1062 | int wl1271_acx_sg_enable(struct wl1271 *wl); | 1008 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1063 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1009 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1064 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1010 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
1065 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); | 1011 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 2be76ee42bb9..41c6affbee29 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "wl1271_acx.h" | 26 | #include "wl1271_acx.h" |
27 | #include "wl1271_reg.h" | 27 | #include "wl1271_reg.h" |
28 | #include "wl1271_boot.h" | 28 | #include "wl1271_boot.h" |
29 | #include "wl1271_spi.h" | ||
30 | #include "wl1271_io.h" | 29 | #include "wl1271_io.h" |
31 | #include "wl1271_event.h" | 30 | #include "wl1271_event.h" |
32 | 31 | ||
@@ -229,6 +228,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
229 | nvs_len = sizeof(wl->nvs->nvs); | 228 | nvs_len = sizeof(wl->nvs->nvs); |
230 | nvs_ptr = (u8 *)wl->nvs->nvs; | 229 | nvs_ptr = (u8 *)wl->nvs->nvs; |
231 | 230 | ||
231 | /* update current MAC address to NVS */ | ||
232 | nvs_ptr[11] = wl->mac_addr[0]; | ||
233 | nvs_ptr[10] = wl->mac_addr[1]; | ||
234 | nvs_ptr[6] = wl->mac_addr[2]; | ||
235 | nvs_ptr[5] = wl->mac_addr[3]; | ||
236 | nvs_ptr[4] = wl->mac_addr[4]; | ||
237 | nvs_ptr[3] = wl->mac_addr[5]; | ||
238 | |||
232 | /* | 239 | /* |
233 | * Layout before the actual NVS tables: | 240 | * Layout before the actual NVS tables: |
234 | * 1 byte : burst length. | 241 | * 1 byte : burst length. |
@@ -299,7 +306,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
299 | 306 | ||
300 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 307 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
301 | { | 308 | { |
302 | enable_irq(wl->irq); | 309 | wl1271_enable_interrupts(wl); |
303 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 310 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
304 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 311 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
305 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 312 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 36a64e06f290..d005729e0312 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -26,10 +26,10 @@ | |||
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 | 30 | ||
30 | #include "wl1271.h" | 31 | #include "wl1271.h" |
31 | #include "wl1271_reg.h" | 32 | #include "wl1271_reg.h" |
32 | #include "wl1271_spi.h" | ||
33 | #include "wl1271_io.h" | 33 | #include "wl1271_io.h" |
34 | #include "wl1271_acx.h" | 34 | #include "wl1271_acx.h" |
35 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
@@ -248,7 +248,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
248 | return ret; | 248 | return ret; |
249 | } | 249 | } |
250 | 250 | ||
251 | int wl1271_cmd_join(struct wl1271 *wl) | 251 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) |
252 | { | 252 | { |
253 | static bool do_cal = true; | 253 | static bool do_cal = true; |
254 | struct wl1271_cmd_join *join; | 254 | struct wl1271_cmd_join *join; |
@@ -279,16 +279,7 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
279 | 279 | ||
280 | join->rx_config_options = cpu_to_le32(wl->rx_config); | 280 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
281 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); | 281 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
282 | join->bss_type = wl->bss_type; | 282 | join->bss_type = bss_type; |
283 | |||
284 | /* | ||
285 | * FIXME: disable temporarily all filters because after commit | ||
286 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
287 | * association. The filter logic needs to be implemented properly | ||
288 | * and once that is done, this hack can be removed. | ||
289 | */ | ||
290 | join->rx_config_options = cpu_to_le32(0); | ||
291 | join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); | ||
292 | 283 | ||
293 | if (wl->band == IEEE80211_BAND_2GHZ) | 284 | if (wl->band == IEEE80211_BAND_2GHZ) |
294 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | 285 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | |
@@ -319,8 +310,7 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
319 | 310 | ||
320 | /* reset TX security counters */ | 311 | /* reset TX security counters */ |
321 | wl->tx_security_last_seq = 0; | 312 | wl->tx_security_last_seq = 0; |
322 | wl->tx_security_seq_16 = 0; | 313 | wl->tx_security_seq = 0; |
323 | wl->tx_security_seq_32 = 0; | ||
324 | 314 | ||
325 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); | 315 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); |
326 | if (ret < 0) { | 316 | if (ret < 0) { |
@@ -548,9 +538,9 @@ out: | |||
548 | return ret; | 538 | return ret; |
549 | } | 539 | } |
550 | 540 | ||
551 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 541 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
552 | u8 active_scan, u8 high_prio, u8 band, | 542 | const u8 *ie, size_t ie_len, u8 active_scan, |
553 | u8 probe_requests) | 543 | u8 high_prio, u8 band, u8 probe_requests) |
554 | { | 544 | { |
555 | 545 | ||
556 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 546 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
@@ -621,12 +611,13 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
621 | 611 | ||
622 | params->params.num_channels = j; | 612 | params->params.num_channels = j; |
623 | 613 | ||
624 | if (len && ssid) { | 614 | if (ssid_len && ssid) { |
625 | params->params.ssid_len = len; | 615 | params->params.ssid_len = ssid_len; |
626 | memcpy(params->params.ssid, ssid, len); | 616 | memcpy(params->params.ssid, ssid, ssid_len); |
627 | } | 617 | } |
628 | 618 | ||
629 | ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); | 619 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, |
620 | ie, ie_len, ieee_band); | ||
630 | if (ret < 0) { | 621 | if (ret < 0) { |
631 | wl1271_error("PROBE request template failed"); | 622 | wl1271_error("PROBE request template failed"); |
632 | goto out; | 623 | goto out; |
@@ -657,9 +648,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
657 | wl->scan.active = active_scan; | 648 | wl->scan.active = active_scan; |
658 | wl->scan.high_prio = high_prio; | 649 | wl->scan.high_prio = high_prio; |
659 | wl->scan.probe_requests = probe_requests; | 650 | wl->scan.probe_requests = probe_requests; |
660 | if (len && ssid) { | 651 | if (ssid_len && ssid) { |
661 | wl->scan.ssid_len = len; | 652 | wl->scan.ssid_len = ssid_len; |
662 | memcpy(wl->scan.ssid, ssid, len); | 653 | memcpy(wl->scan.ssid, ssid, ssid_len); |
663 | } else | 654 | } else |
664 | wl->scan.ssid_len = 0; | 655 | wl->scan.ssid_len = 0; |
665 | } | 656 | } |
@@ -716,155 +707,102 @@ out: | |||
716 | return ret; | 707 | return ret; |
717 | } | 708 | } |
718 | 709 | ||
719 | static int wl1271_build_basic_rates(u8 *rates, u8 band) | 710 | int wl1271_cmd_build_null_data(struct wl1271 *wl) |
720 | { | 711 | { |
721 | u8 index = 0; | 712 | struct sk_buff *skb = NULL; |
722 | 713 | int size; | |
723 | if (band == IEEE80211_BAND_2GHZ) { | 714 | void *ptr; |
724 | rates[index++] = | 715 | int ret = -ENOMEM; |
725 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | ||
726 | rates[index++] = | ||
727 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
728 | rates[index++] = | ||
729 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
730 | rates[index++] = | ||
731 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
732 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
733 | rates[index++] = | ||
734 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; | ||
735 | rates[index++] = | ||
736 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; | ||
737 | rates[index++] = | ||
738 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
739 | } else { | ||
740 | wl1271_error("build_basic_rates invalid band: %d", band); | ||
741 | } | ||
742 | 716 | ||
743 | return index; | ||
744 | } | ||
745 | 717 | ||
746 | static int wl1271_build_extended_rates(u8 *rates, u8 band) | 718 | if (wl->bss_type == BSS_TYPE_IBSS) { |
747 | { | 719 | size = sizeof(struct wl12xx_null_data_template); |
748 | u8 index = 0; | 720 | ptr = NULL; |
749 | |||
750 | if (band == IEEE80211_BAND_2GHZ) { | ||
751 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | ||
752 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | ||
753 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | ||
754 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | ||
755 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | ||
756 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | ||
757 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | ||
758 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
759 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
760 | rates[index++] = | ||
761 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; | ||
762 | rates[index++] = | ||
763 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; | ||
764 | rates[index++] = | ||
765 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
766 | rates[index++] = | ||
767 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; | ||
768 | rates[index++] = | ||
769 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; | ||
770 | rates[index++] = | ||
771 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; | ||
772 | } else { | 721 | } else { |
773 | wl1271_error("build_basic_rates invalid band: %d", band); | 722 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
723 | if (!skb) | ||
724 | goto out; | ||
725 | size = skb->len; | ||
726 | ptr = skb->data; | ||
774 | } | 727 | } |
775 | 728 | ||
776 | return index; | 729 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size); |
777 | } | ||
778 | 730 | ||
779 | int wl1271_cmd_build_null_data(struct wl1271 *wl) | 731 | out: |
780 | { | 732 | dev_kfree_skb(skb); |
781 | struct wl12xx_null_data_template template; | 733 | if (ret) |
782 | 734 | wl1271_warning("cmd buld null data failed %d", ret); | |
783 | if (!is_zero_ether_addr(wl->bssid)) { | ||
784 | memcpy(template.header.da, wl->bssid, ETH_ALEN); | ||
785 | memcpy(template.header.bssid, wl->bssid, ETH_ALEN); | ||
786 | } else { | ||
787 | memset(template.header.da, 0xff, ETH_ALEN); | ||
788 | memset(template.header.bssid, 0xff, ETH_ALEN); | ||
789 | } | ||
790 | |||
791 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | ||
792 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
793 | IEEE80211_STYPE_NULLFUNC | | ||
794 | IEEE80211_FCTL_TODS); | ||
795 | 735 | ||
796 | return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, | 736 | return ret; |
797 | sizeof(template)); | ||
798 | 737 | ||
799 | } | 738 | } |
800 | 739 | ||
801 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 740 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) |
802 | { | 741 | { |
803 | struct wl12xx_ps_poll_template template; | 742 | struct sk_buff *skb; |
804 | 743 | int ret = 0; | |
805 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | ||
806 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | ||
807 | |||
808 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
809 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | ||
810 | 744 | ||
811 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 745 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); |
746 | if (!skb) | ||
747 | goto out; | ||
812 | 748 | ||
813 | return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, | 749 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
814 | sizeof(template)); | 750 | skb->len); |
815 | 751 | ||
752 | out: | ||
753 | dev_kfree_skb(skb); | ||
754 | return ret; | ||
816 | } | 755 | } |
817 | 756 | ||
818 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, | 757 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
819 | u8 band) | 758 | const u8 *ssid, size_t ssid_len, |
759 | const u8 *ie, size_t ie_len, u8 band) | ||
820 | { | 760 | { |
821 | struct wl12xx_probe_req_template template; | 761 | struct sk_buff *skb; |
822 | struct wl12xx_ie_rates *rates; | ||
823 | char *ptr; | ||
824 | u16 size; | ||
825 | int ret; | 762 | int ret; |
826 | 763 | ||
827 | ptr = (char *)&template; | 764 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
828 | size = sizeof(struct ieee80211_header); | 765 | ie, ie_len); |
829 | 766 | if (!skb) { | |
830 | memset(template.header.da, 0xff, ETH_ALEN); | 767 | ret = -ENOMEM; |
831 | memset(template.header.bssid, 0xff, ETH_ALEN); | 768 | goto out; |
832 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 769 | } |
833 | template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 770 | |
834 | 771 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | |
835 | /* IEs */ | ||
836 | /* SSID */ | ||
837 | template.ssid.header.id = WLAN_EID_SSID; | ||
838 | template.ssid.header.len = ssid_len; | ||
839 | if (ssid_len && ssid) | ||
840 | memcpy(template.ssid.ssid, ssid, ssid_len); | ||
841 | size += sizeof(struct wl12xx_ie_header) + ssid_len; | ||
842 | ptr += size; | ||
843 | |||
844 | /* Basic Rates */ | ||
845 | rates = (struct wl12xx_ie_rates *)ptr; | ||
846 | rates->header.id = WLAN_EID_SUPP_RATES; | ||
847 | rates->header.len = wl1271_build_basic_rates(rates->rates, band); | ||
848 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
849 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
850 | |||
851 | /* Extended rates */ | ||
852 | rates = (struct wl12xx_ie_rates *)ptr; | ||
853 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | ||
854 | rates->header.len = wl1271_build_extended_rates(rates->rates, band); | ||
855 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
856 | |||
857 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | ||
858 | 772 | ||
859 | if (band == IEEE80211_BAND_2GHZ) | 773 | if (band == IEEE80211_BAND_2GHZ) |
860 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 774 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
861 | &template, size); | 775 | skb->data, skb->len); |
862 | else | 776 | else |
863 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 777 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
864 | &template, size); | 778 | skb->data, skb->len); |
779 | |||
780 | out: | ||
781 | dev_kfree_skb(skb); | ||
865 | return ret; | 782 | return ret; |
866 | } | 783 | } |
867 | 784 | ||
785 | int wl1271_build_qos_null_data(struct wl1271 *wl) | ||
786 | { | ||
787 | struct ieee80211_qos_hdr template; | ||
788 | |||
789 | memset(&template, 0, sizeof(template)); | ||
790 | |||
791 | memcpy(template.addr1, wl->bssid, ETH_ALEN); | ||
792 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); | ||
793 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
794 | |||
795 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
796 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
797 | IEEE80211_FCTL_TODS); | ||
798 | |||
799 | /* FIXME: not sure what priority to use here */ | ||
800 | template.qos_ctrl = cpu_to_le16(0); | ||
801 | |||
802 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | ||
803 | sizeof(template)); | ||
804 | } | ||
805 | |||
868 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 806 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
869 | { | 807 | { |
870 | struct wl1271_cmd_set_keys *cmd; | 808 | struct wl1271_cmd_set_keys *cmd; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 2dc06c73532b..6324bbf36843 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,17 @@ 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); |
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); | ||
53 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 55 | 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, | 56 | 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, | 57 | u8 key_size, const u8 *key, const u8 *addr, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 6f9e75cc5640..7fcfe06b1412 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -65,110 +65,318 @@ 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_SG_DISABLE = 0, | ||
70 | CONF_SG_PROTECTIVE, | ||
71 | CONF_SG_OPPORTUNISTIC | ||
72 | }; | ||
73 | |||
74 | enum { | ||
69 | /* | 75 | /* |
70 | * Defines the PER threshold in PPM of the BT voice of which reaching | 76 | * 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 | * | 77 | * |
75 | * Unit: PER value in PPM (parts per million) | 78 | * Range: 0 - 10000000 |
76 | * #Error_packets / #Total_packets | 79 | */ |
80 | CONF_SG_BT_PER_THRESHOLD = 0, | ||
77 | 81 | ||
78 | * Range: u32 | 82 | /* |
83 | * Number of consequent RX_ACTIVE activities to override BT voice | ||
84 | * frames to ensure WLAN connection | ||
85 | * | ||
86 | * Range: 0 - 100 | ||
87 | */ | ||
88 | CONF_SG_HV3_MAX_OVERRIDE, | ||
89 | |||
90 | /* | ||
91 | * Defines the PER threshold of the BT voice | ||
92 | * | ||
93 | * Range: 0 - 65000 | ||
94 | */ | ||
95 | CONF_SG_BT_NFS_SAMPLE_INTERVAL, | ||
96 | |||
97 | /* | ||
98 | * Defines the load ratio of BT | ||
99 | * | ||
100 | * Range: 0 - 100 (%) | ||
101 | */ | ||
102 | CONF_SG_BT_LOAD_RATIO, | ||
103 | |||
104 | /* | ||
105 | * Defines whether the SG will force WLAN host to enter/exit PSM | ||
106 | * | ||
107 | * Range: 1 - SG can force, 0 - host handles PSM | ||
108 | */ | ||
109 | CONF_SG_AUTO_PS_MODE, | ||
110 | |||
111 | /* | ||
112 | * Compensation percentage of probe requests when scan initiated | ||
113 | * during BT voice/ACL link. | ||
114 | * | ||
115 | * Range: 0 - 255 (%) | ||
116 | */ | ||
117 | CONF_SG_AUTO_SCAN_PROBE_REQ, | ||
118 | |||
119 | /* | ||
120 | * Compensation percentage of probe requests when active scan initiated | ||
121 | * during BT voice | ||
122 | * | ||
123 | * Range: 0 - 255 (%) | ||
124 | */ | ||
125 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, | ||
126 | |||
127 | /* | ||
128 | * Defines antenna configuration (single/dual antenna) | ||
129 | * | ||
130 | * Range: 0 - single antenna, 1 - dual antenna | ||
131 | */ | ||
132 | CONF_SG_ANTENNA_CONFIGURATION, | ||
133 | |||
134 | /* | ||
135 | * The threshold (percent) of max consequtive beacon misses before | ||
136 | * increasing priority of beacon reception. | ||
137 | * | ||
138 | * Range: 0 - 100 (%) | ||
139 | */ | ||
140 | CONF_SG_BEACON_MISS_PERCENT, | ||
141 | |||
142 | /* | ||
143 | * The rate threshold below which receiving a data frame from the AP | ||
144 | * will increase the priority of the data frame above BT traffic. | ||
145 | * | ||
146 | * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 | ||
147 | */ | ||
148 | CONF_SG_RATE_ADAPT_THRESH, | ||
149 | |||
150 | /* | ||
151 | * Not used currently. | ||
152 | * | ||
153 | * Range: 0 | ||
154 | */ | ||
155 | CONF_SG_RATE_ADAPT_SNR, | ||
156 | |||
157 | /* | ||
158 | * Configure the min and max time BT gains the antenna | ||
159 | * in WLAN PSM / BT master basic rate | ||
160 | * | ||
161 | * Range: 0 - 255 (ms) | ||
162 | */ | ||
163 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, | ||
164 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, | ||
165 | |||
166 | /* | ||
167 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
168 | * in WLAN PSM / BT master basic rate | ||
169 | * | ||
170 | * Range: 0 - 255 (ms) | ||
171 | */ | ||
172 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, | ||
173 | |||
174 | /* | ||
175 | * Configure the min and max time BT gains the antenna | ||
176 | * in WLAN PSM / BT slave basic rate | ||
177 | * | ||
178 | * Range: 0 - 255 (ms) | ||
79 | */ | 179 | */ |
80 | u32 per_threshold; | 180 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, |
181 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, | ||
81 | 182 | ||
82 | /* | 183 | /* |
83 | * This value is an absolute time in micro-seconds to limit the | 184 | * The time after it expires no new WLAN trigger frame is trasmitted |
84 | * maximum scan duration compensation while in SG | 185 | * in WLAN PSM / BT slave basic rate |
186 | * | ||
187 | * Range: 0 - 255 (ms) | ||
85 | */ | 188 | */ |
86 | u32 max_scan_compensation_time; | 189 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, |
87 | 190 | ||
88 | /* Defines the PER threshold of the BT voice of which reaching this | 191 | /* |
89 | * value will trigger raising the priority of the BT voice until next | 192 | * Configure the min and max time BT gains the antenna |
90 | * NFS sample interval time as defined in sample_interval. | 193 | * in WLAN PSM / BT master EDR |
91 | * | 194 | * |
92 | * Unit: msec | 195 | * Range: 0 - 255 (ms) |
93 | * Range: 1-65000 | ||
94 | */ | 196 | */ |
95 | u16 nfs_sample_interval; | 197 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, |
198 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, | ||
96 | 199 | ||
97 | /* | 200 | /* |
98 | * Defines the load ratio for the BT. | 201 | * The time after it expires no new WLAN trigger frame is trasmitted |
99 | * The WLAN ratio is: 100 - load_ratio | 202 | * in WLAN PSM / BT master EDR |
100 | * | 203 | * |
101 | * Unit: Percent | 204 | * Range: 0 - 255 (ms) |
102 | * Range: 0-100 | ||
103 | */ | 205 | */ |
104 | u8 load_ratio; | 206 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, |
105 | 207 | ||
106 | /* | 208 | /* |
107 | * true - Co-ex is allowed to enter/exit P.S automatically and | 209 | * Configure the min and max time BT gains the antenna |
108 | * transparently to the host | 210 | * in WLAN PSM / BT slave EDR |
109 | * | 211 | * |
110 | * false - Co-ex is disallowed to enter/exit P.S and will trigger an | 212 | * Range: 0 - 255 (ms) |
111 | * event to the host to notify for the need to enter/exit P.S | 213 | */ |
112 | * due to BT change state | 214 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, |
215 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, | ||
216 | |||
217 | /* | ||
218 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
219 | * in WLAN PSM / BT slave EDR | ||
113 | * | 220 | * |
221 | * Range: 0 - 255 (ms) | ||
114 | */ | 222 | */ |
115 | u8 auto_ps_mode; | 223 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, |
116 | 224 | ||
117 | /* | 225 | /* |
118 | * This parameter defines the compensation percentage of num of probe | 226 | * RX guard time before the beginning of a new BT voice frame during |
119 | * requests in case scan is initiated during BT voice/BT ACL | 227 | * which no new WLAN trigger frame is transmitted. |
120 | * guaranteed link. | ||
121 | * | 228 | * |
122 | * Unit: Percent | 229 | * Range: 0 - 100000 (us) |
123 | * Range: 0-255 (0 - No compensation) | ||
124 | */ | 230 | */ |
125 | u8 probe_req_compensation; | 231 | CONF_SG_RXT, |
126 | 232 | ||
127 | /* | 233 | /* |
128 | * This parameter defines the compensation percentage of scan window | 234 | * TX guard time before the beginning of a new BT voice frame during |
129 | * size in case scan is initiated during BT voice/BT ACL Guaranteed | 235 | * which no new WLAN frame is transmitted. |
130 | * link. | ||
131 | * | 236 | * |
132 | * Unit: Percent | 237 | * Range: 0 - 100000 (us) |
133 | * Range: 0-255 (0 - No compensation) | ||
134 | */ | 238 | */ |
135 | u8 scan_window_compensation; | 239 | |
240 | CONF_SG_TXT, | ||
136 | 241 | ||
137 | /* | 242 | /* |
138 | * Defines the antenna configuration. | 243 | * Enable adaptive RXT/TXT algorithm. If disabled, the host values |
244 | * will be utilized. | ||
139 | * | 245 | * |
140 | * Range: 0 - Single Antenna; 1 - Dual Antenna | 246 | * Range: 0 - disable, 1 - enable |
141 | */ | 247 | */ |
142 | u8 antenna_config; | 248 | CONF_SG_ADAPTIVE_RXT_TXT, |
143 | 249 | ||
144 | /* | 250 | /* |
145 | * The percent out of the Max consecutive beacon miss roaming trigger | 251 | * The used WLAN legacy service period during active BT ACL link |
146 | * which is the threshold for raising the priority of beacon | ||
147 | * reception. | ||
148 | * | 252 | * |
149 | * Range: 1-100 | 253 | * Range: 0 - 255 (ms) |
150 | * N = MaxConsecutiveBeaconMiss | ||
151 | * P = coexMaxConsecutiveBeaconMissPrecent | ||
152 | * Threshold = MIN( N-1, round(N * P / 100)) | ||
153 | */ | 254 | */ |
154 | u8 beacon_miss_threshold; | 255 | CONF_SG_PS_POLL_TIMEOUT, |
155 | 256 | ||
156 | /* | 257 | /* |
157 | * The RX rate threshold below which rate adaptation is assumed to be | 258 | * The used WLAN UPSD service period during active BT ACL link |
158 | * occurring at the AP which will raise priority for ACTIVE_RX and RX | ||
159 | * SP. | ||
160 | * | 259 | * |
161 | * Range: HW_BIT_RATE_* | 260 | * Range: 0 - 255 (ms) |
162 | */ | 261 | */ |
163 | u32 rate_adaptation_threshold; | 262 | CONF_SG_UPSD_TIMEOUT, |
164 | 263 | ||
165 | /* | 264 | /* |
166 | * The SNR above which the RX rate threshold indicating AP rate | 265 | * Configure the min and max time BT gains the antenna |
167 | * adaptation is valid | 266 | * in WLAN Active / BT master EDR |
168 | * | 267 | * |
169 | * Range: -128 - 127 | 268 | * Range: 0 - 255 (ms) |
170 | */ | 269 | */ |
171 | s8 rate_adaptation_snr; | 270 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, |
271 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, | ||
272 | |||
273 | /* | ||
274 | * The maximum time WLAN can gain the antenna for | ||
275 | * in WLAN Active / BT master EDR | ||
276 | * | ||
277 | * Range: 0 - 255 (ms) | ||
278 | */ | ||
279 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, | ||
280 | |||
281 | /* | ||
282 | * Configure the min and max time BT gains the antenna | ||
283 | * in WLAN Active / BT slave EDR | ||
284 | * | ||
285 | * Range: 0 - 255 (ms) | ||
286 | */ | ||
287 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, | ||
288 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, | ||
289 | |||
290 | /* | ||
291 | * The maximum time WLAN can gain the antenna for | ||
292 | * in WLAN Active / BT slave EDR | ||
293 | * | ||
294 | * Range: 0 - 255 (ms) | ||
295 | */ | ||
296 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, | ||
297 | |||
298 | /* | ||
299 | * Configure the min and max time BT gains the antenna | ||
300 | * in WLAN Active / BT basic rate | ||
301 | * | ||
302 | * Range: 0 - 255 (ms) | ||
303 | */ | ||
304 | CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, | ||
305 | CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, | ||
306 | |||
307 | /* | ||
308 | * The maximum time WLAN can gain the antenna for | ||
309 | * in WLAN Active / BT basic rate | ||
310 | * | ||
311 | * Range: 0 - 255 (ms) | ||
312 | */ | ||
313 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, | ||
314 | |||
315 | /* | ||
316 | * Compensation percentage of WLAN passive scan window if initiated | ||
317 | * during BT voice | ||
318 | * | ||
319 | * Range: 0 - 1000 (%) | ||
320 | */ | ||
321 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, | ||
322 | |||
323 | /* | ||
324 | * Compensation percentage of WLAN passive scan window if initiated | ||
325 | * during BT A2DP | ||
326 | * | ||
327 | * Range: 0 - 1000 (%) | ||
328 | */ | ||
329 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, | ||
330 | |||
331 | /* | ||
332 | * Fixed time ensured for BT traffic to gain the antenna during WLAN | ||
333 | * passive scan. | ||
334 | * | ||
335 | * Range: 0 - 1000 ms | ||
336 | */ | ||
337 | CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, | ||
338 | |||
339 | /* | ||
340 | * Fixed time ensured for WLAN traffic to gain the antenna during WLAN | ||
341 | * passive scan. | ||
342 | * | ||
343 | * Range: 0 - 1000 ms | ||
344 | */ | ||
345 | CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, | ||
346 | |||
347 | /* | ||
348 | * Number of consequent BT voice frames not interrupted by WLAN | ||
349 | * | ||
350 | * Range: 0 - 100 | ||
351 | */ | ||
352 | CONF_SG_HV3_MAX_SERVED, | ||
353 | |||
354 | /* | ||
355 | * Protection time of the DHCP procedure. | ||
356 | * | ||
357 | * Range: 0 - 100000 (ms) | ||
358 | */ | ||
359 | CONF_SG_DHCP_TIME, | ||
360 | |||
361 | /* | ||
362 | * Compensation percentage of WLAN active scan window if initiated | ||
363 | * during BT A2DP | ||
364 | * | ||
365 | * Range: 0 - 1000 (%) | ||
366 | */ | ||
367 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, | ||
368 | CONF_SG_TEMP_PARAM_1, | ||
369 | CONF_SG_TEMP_PARAM_2, | ||
370 | CONF_SG_TEMP_PARAM_3, | ||
371 | CONF_SG_TEMP_PARAM_4, | ||
372 | CONF_SG_TEMP_PARAM_5, | ||
373 | CONF_SG_PARAMS_MAX, | ||
374 | CONF_SG_PARAMS_ALL = 0xff | ||
375 | }; | ||
376 | |||
377 | struct conf_sg_settings { | ||
378 | __le32 params[CONF_SG_PARAMS_MAX]; | ||
379 | u8 state; | ||
172 | }; | 380 | }; |
173 | 381 | ||
174 | enum conf_rx_queue_type { | 382 | enum conf_rx_queue_type { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index 8d7588ca68fd..3c0f5b1ac272 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "wl1271.h" | 28 | #include "wl1271.h" |
29 | #include "wl1271_acx.h" | 29 | #include "wl1271_acx.h" |
30 | #include "wl1271_ps.h" | 30 | #include "wl1271_ps.h" |
31 | #include "wl1271_io.h" | ||
31 | 32 | ||
32 | /* ms */ | 33 | /* ms */ |
33 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 34 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
@@ -276,13 +277,10 @@ static ssize_t gpio_power_write(struct file *file, | |||
276 | goto out; | 277 | goto out; |
277 | } | 278 | } |
278 | 279 | ||
279 | if (value) { | 280 | if (value) |
280 | wl->set_power(true); | 281 | wl1271_power_on(wl); |
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 282 | else |
282 | } else { | 283 | wl1271_power_off(wl); |
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | 284 | ||
287 | out: | 285 | out: |
288 | mutex_unlock(&wl->mutex); | 286 | mutex_unlock(&wl->mutex); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 7468ef10194b..4d35af96c597 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" |
@@ -45,7 +44,9 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
45 | * scanning as it checks that. | 44 | * scanning as it checks that. |
46 | */ | 45 | */ |
47 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 46 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
47 | /* FIXME: ie missing! */ | ||
48 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 48 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
49 | NULL, 0, | ||
49 | wl->scan.active, | 50 | wl->scan.active, |
50 | wl->scan.high_prio, | 51 | wl->scan.high_prio, |
51 | WL1271_SCAN_BAND_5_GHZ, | 52 | WL1271_SCAN_BAND_5_GHZ, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 86c30a86a456..d9335fc2a575 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -160,11 +160,11 @@ int wl1271_init_pta(struct wl1271 *wl) | |||
160 | { | 160 | { |
161 | int ret; | 161 | int ret; |
162 | 162 | ||
163 | ret = wl1271_acx_sg_enable(wl); | 163 | ret = wl1271_acx_sg_cfg(wl); |
164 | if (ret < 0) | 164 | if (ret < 0) |
165 | return ret; | 165 | return ret; |
166 | 166 | ||
167 | ret = wl1271_acx_sg_cfg(wl); | 167 | ret = wl1271_acx_sg_enable(wl, wl->sg_enabled); |
168 | if (ret < 0) | 168 | if (ret < 0) |
169 | return ret; | 169 | return ret; |
170 | 170 | ||
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..d8837ef0bb40 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -25,31 +25,49 @@ | |||
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 | { |
@@ -65,4 +83,87 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 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 2a864b24291d..6036d0206fec 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -22,22 +22,18 @@ | |||
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 | 33 | ||
37 | #include "wl1271.h" | 34 | #include "wl1271.h" |
38 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 36 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | ||
41 | #include "wl1271_io.h" | 37 | #include "wl1271_io.h" |
42 | #include "wl1271_event.h" | 38 | #include "wl1271_event.h" |
43 | #include "wl1271_tx.h" | 39 | #include "wl1271_tx.h" |
@@ -53,17 +49,57 @@ | |||
53 | 49 | ||
54 | static struct conf_drv_settings default_conf = { | 50 | static struct conf_drv_settings default_conf = { |
55 | .sg = { | 51 | .sg = { |
56 | .per_threshold = 7500, | 52 | .params = { |
57 | .max_scan_compensation_time = 120000, | 53 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
58 | .nfs_sample_interval = 400, | 54 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
59 | .load_ratio = 50, | 55 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
60 | .auto_ps_mode = 0, | 56 | [CONF_SG_BT_LOAD_RATIO] = 50, |
61 | .probe_req_compensation = 170, | 57 | [CONF_SG_AUTO_PS_MODE] = 0, |
62 | .scan_window_compensation = 50, | 58 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
63 | .antenna_config = 0, | 59 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
64 | .beacon_miss_threshold = 60, | 60 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, |
65 | .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, | 61 | [CONF_SG_BEACON_MISS_PERCENT] = 60, |
66 | .rate_adaptation_snr = 0 | 62 | [CONF_SG_RATE_ADAPT_THRESH] = 12, |
63 | [CONF_SG_RATE_ADAPT_SNR] = 0, | ||
64 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
65 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, | ||
66 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, | ||
67 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
68 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, | ||
69 | /* Note: with UPSD, this should be 4 */ | ||
70 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, | ||
71 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
72 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
73 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, | ||
74 | /* Note: with UPDS, this should be 15 */ | ||
75 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
76 | /* Note: with UPDS, this should be 50 */ | ||
77 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, | ||
78 | /* Note: with UPDS, this should be 10 */ | ||
79 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, | ||
80 | [CONF_SG_RXT] = 1200, | ||
81 | [CONF_SG_TXT] = 1000, | ||
82 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
83 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
84 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
85 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
86 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
87 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
88 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
89 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
90 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
91 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
92 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
93 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
94 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
95 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
96 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
97 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
98 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
99 | [CONF_SG_DHCP_TIME] = 5000, | ||
100 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
101 | }, | ||
102 | .state = CONF_SG_PROTECTIVE, | ||
67 | }, | 103 | }, |
68 | .rx = { | 104 | .rx = { |
69 | .rx_msdu_life_time = 512000, | 105 | .rx_msdu_life_time = 512000, |
@@ -245,6 +281,21 @@ static struct conf_drv_settings default_conf = { | |||
245 | } | 281 | } |
246 | }; | 282 | }; |
247 | 283 | ||
284 | static void wl1271_device_release(struct device *dev) | ||
285 | { | ||
286 | |||
287 | } | ||
288 | |||
289 | static struct platform_device wl1271_device = { | ||
290 | .name = "wl1271", | ||
291 | .id = -1, | ||
292 | |||
293 | /* device model insists to have a release function */ | ||
294 | .dev = { | ||
295 | .release = wl1271_device_release, | ||
296 | }, | ||
297 | }; | ||
298 | |||
248 | static LIST_HEAD(wl_list); | 299 | static LIST_HEAD(wl_list); |
249 | 300 | ||
250 | static void wl1271_conf_init(struct wl1271 *wl) | 301 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -364,30 +415,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
364 | return ret; | 415 | return ret; |
365 | } | 416 | } |
366 | 417 | ||
367 | static void wl1271_disable_interrupts(struct wl1271 *wl) | ||
368 | { | ||
369 | disable_irq(wl->irq); | ||
370 | } | ||
371 | |||
372 | static void wl1271_power_off(struct wl1271 *wl) | ||
373 | { | ||
374 | wl->set_power(false); | ||
375 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
376 | } | ||
377 | |||
378 | static void wl1271_power_on(struct wl1271 *wl) | ||
379 | { | ||
380 | wl->set_power(true); | ||
381 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | ||
383 | |||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 418 | static void wl1271_fw_status(struct wl1271 *wl, |
385 | struct wl1271_fw_status *status) | 419 | struct wl1271_fw_status *status) |
386 | { | 420 | { |
421 | struct timespec ts; | ||
387 | u32 total = 0; | 422 | u32 total = 0; |
388 | int i; | 423 | int i; |
389 | 424 | ||
390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 425 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
391 | 426 | ||
392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 427 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
393 | "drv_rx_counter = %d, tx_results_counter = %d)", | 428 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -412,14 +447,19 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
412 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 447 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
413 | 448 | ||
414 | /* update the host-chipset time offset */ | 449 | /* update the host-chipset time offset */ |
415 | wl->time_offset = jiffies_to_usecs(jiffies) - | 450 | getnstimeofday(&ts); |
416 | le32_to_cpu(status->fw_localtime); | 451 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
452 | (s64)le32_to_cpu(status->fw_localtime); | ||
417 | } | 453 | } |
418 | 454 | ||
455 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
456 | |||
419 | static void wl1271_irq_work(struct work_struct *work) | 457 | static void wl1271_irq_work(struct work_struct *work) |
420 | { | 458 | { |
421 | int ret; | 459 | int ret; |
422 | u32 intr; | 460 | u32 intr; |
461 | int loopcount = WL1271_IRQ_MAX_LOOPS; | ||
462 | unsigned long flags; | ||
423 | struct wl1271 *wl = | 463 | struct wl1271 *wl = |
424 | container_of(work, struct wl1271, irq_work); | 464 | container_of(work, struct wl1271, irq_work); |
425 | 465 | ||
@@ -427,91 +467,77 @@ static void wl1271_irq_work(struct work_struct *work) | |||
427 | 467 | ||
428 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 468 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
429 | 469 | ||
430 | if (wl->state == WL1271_STATE_OFF) | 470 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
431 | goto out; | 471 | goto out; |
432 | 472 | ||
433 | ret = wl1271_ps_elp_wakeup(wl, true); | 473 | ret = wl1271_ps_elp_wakeup(wl, true); |
434 | if (ret < 0) | 474 | if (ret < 0) |
435 | goto out; | 475 | goto out; |
436 | 476 | ||
437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 477 | spin_lock_irqsave(&wl->wl_lock, flags); |
438 | 478 | while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { | |
439 | wl1271_fw_status(wl, wl->fw_status); | 479 | clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); |
440 | intr = le32_to_cpu(wl->fw_status->intr); | 480 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
441 | if (!intr) { | 481 | loopcount--; |
442 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 482 | |
443 | goto out_sleep; | 483 | wl1271_fw_status(wl, wl->fw_status); |
444 | } | 484 | intr = le32_to_cpu(wl->fw_status->intr); |
485 | if (!intr) { | ||
486 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | ||
487 | continue; | ||
488 | } | ||
445 | 489 | ||
446 | intr &= WL1271_INTR_MASK; | 490 | intr &= WL1271_INTR_MASK; |
447 | 491 | ||
448 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 492 | if (intr & WL1271_ACX_INTR_DATA) { |
449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 493 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
450 | wl1271_event_handle(wl, 0); | ||
451 | } | ||
452 | 494 | ||
453 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 495 | /* check for tx results */ |
454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 496 | if (wl->fw_status->tx_results_counter != |
455 | wl1271_event_handle(wl, 1); | 497 | (wl->tx_results_count & 0xff)) |
456 | } | 498 | wl1271_tx_complete(wl); |
457 | 499 | ||
458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 500 | wl1271_rx(wl, wl->fw_status); |
459 | wl1271_debug(DEBUG_IRQ, | 501 | } |
460 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
461 | 502 | ||
462 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 503 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
463 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 504 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
505 | wl1271_event_handle(wl, 0); | ||
506 | } | ||
464 | 507 | ||
465 | if (intr & WL1271_ACX_INTR_DATA) { | 508 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
466 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 509 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
467 | wl->tx_results_count; | 510 | wl1271_event_handle(wl, 1); |
511 | } | ||
468 | 512 | ||
469 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 513 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
514 | wl1271_debug(DEBUG_IRQ, | ||
515 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
470 | 516 | ||
471 | /* check for tx results */ | 517 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
472 | if (tx_res_cnt) | 518 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
473 | wl1271_tx_complete(wl, tx_res_cnt); | ||
474 | 519 | ||
475 | wl1271_rx(wl, wl->fw_status); | 520 | spin_lock_irqsave(&wl->wl_lock, flags); |
476 | } | 521 | } |
477 | 522 | ||
478 | out_sleep: | 523 | if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) |
479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 524 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 525 | else |
526 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
527 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
528 | |||
481 | wl1271_ps_elp_sleep(wl); | 529 | wl1271_ps_elp_sleep(wl); |
482 | 530 | ||
483 | out: | 531 | out: |
484 | mutex_unlock(&wl->mutex); | 532 | mutex_unlock(&wl->mutex); |
485 | } | 533 | } |
486 | 534 | ||
487 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
488 | { | ||
489 | struct wl1271 *wl; | ||
490 | unsigned long flags; | ||
491 | |||
492 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
493 | |||
494 | wl = cookie; | ||
495 | |||
496 | /* complete the ELP completion */ | ||
497 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
498 | if (wl->elp_compl) { | ||
499 | complete(wl->elp_compl); | ||
500 | wl->elp_compl = NULL; | ||
501 | } | ||
502 | |||
503 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
504 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
505 | |||
506 | return IRQ_HANDLED; | ||
507 | } | ||
508 | |||
509 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 535 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
510 | { | 536 | { |
511 | const struct firmware *fw; | 537 | const struct firmware *fw; |
512 | int ret; | 538 | int ret; |
513 | 539 | ||
514 | ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); | 540 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); |
515 | 541 | ||
516 | if (ret < 0) { | 542 | if (ret < 0) { |
517 | wl1271_error("could not get firmware: %d", ret); | 543 | wl1271_error("could not get firmware: %d", ret); |
@@ -544,46 +570,12 @@ out: | |||
544 | return ret; | 570 | return ret; |
545 | } | 571 | } |
546 | 572 | ||
547 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
548 | { | ||
549 | int ret = 0; | ||
550 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
551 | |||
552 | /* get mac address from the NVS */ | ||
553 | wl->mac_addr[0] = nvs_ptr[11]; | ||
554 | wl->mac_addr[1] = nvs_ptr[10]; | ||
555 | wl->mac_addr[2] = nvs_ptr[6]; | ||
556 | wl->mac_addr[3] = nvs_ptr[5]; | ||
557 | wl->mac_addr[4] = nvs_ptr[4]; | ||
558 | wl->mac_addr[5] = nvs_ptr[3]; | ||
559 | |||
560 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
561 | we randomize an address */ | ||
562 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
563 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
564 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
565 | get_random_bytes(wl->mac_addr + 3, 3); | ||
566 | |||
567 | /* update this address to the NVS */ | ||
568 | nvs_ptr[11] = wl->mac_addr[0]; | ||
569 | nvs_ptr[10] = wl->mac_addr[1]; | ||
570 | nvs_ptr[6] = wl->mac_addr[2]; | ||
571 | nvs_ptr[5] = wl->mac_addr[3]; | ||
572 | nvs_ptr[4] = wl->mac_addr[4]; | ||
573 | nvs_ptr[3] = wl->mac_addr[5]; | ||
574 | } | ||
575 | |||
576 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 573 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
582 | { | 574 | { |
583 | const struct firmware *fw; | 575 | const struct firmware *fw; |
584 | int ret; | 576 | int ret; |
585 | 577 | ||
586 | ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); | 578 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); |
587 | 579 | ||
588 | if (ret < 0) { | 580 | if (ret < 0) { |
589 | wl1271_error("could not get nvs file: %d", ret); | 581 | wl1271_error("could not get nvs file: %d", ret); |
@@ -607,8 +599,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
607 | 599 | ||
608 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); | 600 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
609 | 601 | ||
610 | ret = wl1271_update_mac_addr(wl); | ||
611 | |||
612 | out: | 602 | out: |
613 | release_firmware(fw); | 603 | release_firmware(fw); |
614 | 604 | ||
@@ -825,15 +815,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
825 | * The workqueue is slow to process the tx_queue and we need stop | 815 | * The workqueue is slow to process the tx_queue and we need stop |
826 | * the queue here, otherwise the queue will get too long. | 816 | * the queue here, otherwise the queue will get too long. |
827 | */ | 817 | */ |
828 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { | 818 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
829 | ieee80211_stop_queues(wl->hw); | 819 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
830 | 820 | ||
831 | /* | 821 | spin_lock_irqsave(&wl->wl_lock, flags); |
832 | * FIXME: this is racy, the variable is not properly | 822 | ieee80211_stop_queues(wl->hw); |
833 | * protected. Maybe fix this by removing the stupid | ||
834 | * variable altogether and checking the real queue state? | ||
835 | */ | ||
836 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 823 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
824 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
837 | } | 825 | } |
838 | 826 | ||
839 | return NETDEV_TX_OK; | 827 | return NETDEV_TX_OK; |
@@ -928,13 +916,58 @@ static struct notifier_block wl1271_dev_notifier = { | |||
928 | 916 | ||
929 | static int wl1271_op_start(struct ieee80211_hw *hw) | 917 | static int wl1271_op_start(struct ieee80211_hw *hw) |
930 | { | 918 | { |
919 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | ||
920 | |||
921 | /* | ||
922 | * We have to delay the booting of the hardware because | ||
923 | * we need to know the local MAC address before downloading and | ||
924 | * initializing the firmware. The MAC address cannot be changed | ||
925 | * after boot, and without the proper MAC address, the firmware | ||
926 | * will not function properly. | ||
927 | * | ||
928 | * The MAC address is first known when the corresponding interface | ||
929 | * is added. That is where we will initialize the hardware. | ||
930 | */ | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static void wl1271_op_stop(struct ieee80211_hw *hw) | ||
936 | { | ||
937 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
938 | } | ||
939 | |||
940 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | ||
941 | struct ieee80211_vif *vif) | ||
942 | { | ||
931 | struct wl1271 *wl = hw->priv; | 943 | struct wl1271 *wl = hw->priv; |
932 | int retries = WL1271_BOOT_RETRIES; | 944 | int retries = WL1271_BOOT_RETRIES; |
933 | int ret = 0; | 945 | int ret = 0; |
934 | 946 | ||
935 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 947 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
948 | vif->type, vif->addr); | ||
936 | 949 | ||
937 | mutex_lock(&wl->mutex); | 950 | mutex_lock(&wl->mutex); |
951 | if (wl->vif) { | ||
952 | ret = -EBUSY; | ||
953 | goto out; | ||
954 | } | ||
955 | |||
956 | wl->vif = vif; | ||
957 | |||
958 | switch (vif->type) { | ||
959 | case NL80211_IFTYPE_STATION: | ||
960 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
961 | break; | ||
962 | case NL80211_IFTYPE_ADHOC: | ||
963 | wl->bss_type = BSS_TYPE_IBSS; | ||
964 | break; | ||
965 | default: | ||
966 | ret = -EOPNOTSUPP; | ||
967 | goto out; | ||
968 | } | ||
969 | |||
970 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
938 | 971 | ||
939 | if (wl->state != WL1271_STATE_OFF) { | 972 | if (wl->state != WL1271_STATE_OFF) { |
940 | wl1271_error("cannot start because not in off state: %d", | 973 | wl1271_error("cannot start because not in off state: %d", |
@@ -990,19 +1023,20 @@ out: | |||
990 | return ret; | 1023 | return ret; |
991 | } | 1024 | } |
992 | 1025 | ||
993 | static void wl1271_op_stop(struct ieee80211_hw *hw) | 1026 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1027 | struct ieee80211_vif *vif) | ||
994 | { | 1028 | { |
995 | struct wl1271 *wl = hw->priv; | 1029 | struct wl1271 *wl = hw->priv; |
996 | int i; | 1030 | int i; |
997 | 1031 | ||
998 | wl1271_info("down"); | ||
999 | |||
1000 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
1001 | |||
1002 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | 1032 | unregister_inetaddr_notifier(&wl1271_dev_notifier); |
1003 | list_del(&wl->list); | ||
1004 | 1033 | ||
1005 | mutex_lock(&wl->mutex); | 1034 | mutex_lock(&wl->mutex); |
1035 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1036 | |||
1037 | wl1271_info("down"); | ||
1038 | |||
1039 | list_del(&wl->list); | ||
1006 | 1040 | ||
1007 | WARN_ON(wl->state != WL1271_STATE_ON); | 1041 | WARN_ON(wl->state != WL1271_STATE_ON); |
1008 | 1042 | ||
@@ -1040,13 +1074,14 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1040 | wl->tx_results_count = 0; | 1074 | wl->tx_results_count = 0; |
1041 | wl->tx_packets_count = 0; | 1075 | wl->tx_packets_count = 0; |
1042 | wl->tx_security_last_seq = 0; | 1076 | wl->tx_security_last_seq = 0; |
1043 | wl->tx_security_seq_16 = 0; | 1077 | wl->tx_security_seq = 0; |
1044 | wl->tx_security_seq_32 = 0; | ||
1045 | wl->time_offset = 0; | 1078 | wl->time_offset = 0; |
1046 | wl->session_counter = 0; | 1079 | wl->session_counter = 0; |
1047 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1080 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1048 | wl->sta_rate_set = 0; | 1081 | wl->sta_rate_set = 0; |
1049 | wl->flags = 0; | 1082 | wl->flags = 0; |
1083 | wl->vif = NULL; | ||
1084 | wl->filters = 0; | ||
1050 | 1085 | ||
1051 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1086 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1052 | wl->tx_blocks_freed[i] = 0; | 1087 | wl->tx_blocks_freed[i] = 0; |
@@ -1055,119 +1090,39 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1055 | mutex_unlock(&wl->mutex); | 1090 | mutex_unlock(&wl->mutex); |
1056 | } | 1091 | } |
1057 | 1092 | ||
1058 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1093 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1059 | struct ieee80211_vif *vif) | ||
1060 | { | 1094 | { |
1061 | struct wl1271 *wl = hw->priv; | 1095 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1062 | int ret = 0; | 1096 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1063 | |||
1064 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | ||
1065 | vif->type, vif->addr); | ||
1066 | 1097 | ||
1067 | mutex_lock(&wl->mutex); | 1098 | /* combine requested filters with current filter config */ |
1068 | if (wl->vif) { | 1099 | filters = wl->filters | filters; |
1069 | ret = -EBUSY; | ||
1070 | goto out; | ||
1071 | } | ||
1072 | 1100 | ||
1073 | wl->vif = vif; | 1101 | wl1271_debug(DEBUG_FILTERS, "RX filters set: "); |
1074 | 1102 | ||
1075 | switch (vif->type) { | 1103 | if (filters & FIF_PROMISC_IN_BSS) { |
1076 | case NL80211_IFTYPE_STATION: | 1104 | wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); |
1077 | wl->bss_type = BSS_TYPE_STA_BSS; | 1105 | wl->rx_config &= ~CFG_UNI_FILTER_EN; |
1078 | break; | 1106 | wl->rx_config |= CFG_BSSID_FILTER_EN; |
1079 | case NL80211_IFTYPE_ADHOC: | ||
1080 | wl->bss_type = BSS_TYPE_IBSS; | ||
1081 | break; | ||
1082 | default: | ||
1083 | ret = -EOPNOTSUPP; | ||
1084 | goto out; | ||
1085 | } | 1107 | } |
1086 | 1108 | if (filters & FIF_BCN_PRBRESP_PROMISC) { | |
1087 | /* FIXME: what if conf->mac_addr changes? */ | 1109 | wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); |
1088 | 1110 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | |
1089 | out: | 1111 | wl->rx_config &= ~CFG_SSID_FILTER_EN; |
1090 | mutex_unlock(&wl->mutex); | ||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | ||
1095 | struct ieee80211_vif *vif) | ||
1096 | { | ||
1097 | struct wl1271 *wl = hw->priv; | ||
1098 | |||
1099 | mutex_lock(&wl->mutex); | ||
1100 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1101 | wl->vif = NULL; | ||
1102 | mutex_unlock(&wl->mutex); | ||
1103 | } | ||
1104 | |||
1105 | #if 0 | ||
1106 | static int wl1271_op_config_interface(struct ieee80211_hw *hw, | ||
1107 | struct ieee80211_vif *vif, | ||
1108 | struct ieee80211_if_conf *conf) | ||
1109 | { | ||
1110 | struct wl1271 *wl = hw->priv; | ||
1111 | struct sk_buff *beacon; | ||
1112 | int ret; | ||
1113 | |||
1114 | wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", | ||
1115 | conf->bssid); | ||
1116 | wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, | ||
1117 | conf->ssid_len); | ||
1118 | |||
1119 | mutex_lock(&wl->mutex); | ||
1120 | |||
1121 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1122 | if (ret < 0) | ||
1123 | goto out; | ||
1124 | |||
1125 | if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { | ||
1126 | wl1271_debug(DEBUG_MAC80211, "bssid changed"); | ||
1127 | |||
1128 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | ||
1129 | |||
1130 | ret = wl1271_cmd_join(wl); | ||
1131 | if (ret < 0) | ||
1132 | goto out_sleep; | ||
1133 | |||
1134 | ret = wl1271_cmd_build_null_data(wl); | ||
1135 | if (ret < 0) | ||
1136 | goto out_sleep; | ||
1137 | } | 1112 | } |
1138 | 1113 | if (filters & FIF_OTHER_BSS) { | |
1139 | wl->ssid_len = conf->ssid_len; | 1114 | wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); |
1140 | if (wl->ssid_len) | 1115 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; |
1141 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); | 1116 | } |
1142 | 1117 | if (filters & FIF_CONTROL) { | |
1143 | if (conf->changed & IEEE80211_IFCC_BEACON) { | 1118 | wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); |
1144 | beacon = ieee80211_beacon_get(hw, vif); | 1119 | wl->rx_filter |= CFG_RX_CTL_EN; |
1145 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1120 | } |
1146 | beacon->data, beacon->len); | 1121 | if (filters & FIF_FCSFAIL) { |
1147 | 1122 | wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); | |
1148 | if (ret < 0) { | 1123 | wl->rx_filter |= CFG_RX_FCS_ERROR; |
1149 | dev_kfree_skb(beacon); | ||
1150 | goto out_sleep; | ||
1151 | } | ||
1152 | |||
1153 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, | ||
1154 | beacon->data, beacon->len); | ||
1155 | |||
1156 | dev_kfree_skb(beacon); | ||
1157 | |||
1158 | if (ret < 0) | ||
1159 | goto out_sleep; | ||
1160 | } | 1124 | } |
1161 | |||
1162 | out_sleep: | ||
1163 | wl1271_ps_elp_sleep(wl); | ||
1164 | |||
1165 | out: | ||
1166 | mutex_unlock(&wl->mutex); | ||
1167 | |||
1168 | return ret; | ||
1169 | } | 1125 | } |
1170 | #endif | ||
1171 | 1126 | ||
1172 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | 1127 | static int wl1271_join_channel(struct wl1271 *wl, int channel) |
1173 | { | 1128 | { |
@@ -1176,17 +1131,16 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1176 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | 1131 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, |
1177 | 0xad, 0xbe, 0xef }; | 1132 | 0xad, 0xbe, 0xef }; |
1178 | 1133 | ||
1179 | /* the dummy join is not required for ad-hoc */ | ||
1180 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1181 | goto out; | ||
1182 | |||
1183 | /* disable mac filter, so we hear everything */ | ||
1184 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1185 | |||
1186 | wl->channel = channel; | 1134 | wl->channel = channel; |
1187 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1135 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1188 | 1136 | ||
1189 | ret = wl1271_cmd_join(wl); | 1137 | /* pass through frames from all BSS */ |
1138 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1139 | |||
1140 | /* the dummy join is performed always with STATION BSS type to allow | ||
1141 | also ad-hoc mode to listen to the surroundings without sending any | ||
1142 | beacons yet. */ | ||
1143 | ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); | ||
1190 | if (ret < 0) | 1144 | if (ret < 0) |
1191 | goto out; | 1145 | goto out; |
1192 | 1146 | ||
@@ -1208,7 +1162,9 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) | |||
1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1162 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
1209 | wl->channel = 0; | 1163 | wl->channel = 0; |
1210 | memset(wl->bssid, 0, ETH_ALEN); | 1164 | memset(wl->bssid, 0, ETH_ALEN); |
1211 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1165 | |
1166 | /* stop filterting packets based on bssid */ | ||
1167 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1212 | 1168 | ||
1213 | out: | 1169 | out: |
1214 | return ret; | 1170 | return ret; |
@@ -1255,7 +1211,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | 1211 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { |
1256 | wl->channel = channel; | 1212 | wl->channel = channel; |
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | 1213 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ |
1258 | ret = wl1271_cmd_join(wl); | 1214 | ret = wl1271_cmd_join(wl, wl->bss_type); |
1259 | if (ret < 0) | 1215 | if (ret < 0) |
1260 | wl1271_warning("cmd join to update channel failed %d", | 1216 | wl1271_warning("cmd join to update channel failed %d", |
1261 | ret); | 1217 | ret); |
@@ -1272,13 +1228,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1272 | * through the bss_info_changed() hook. | 1228 | * through the bss_info_changed() hook. |
1273 | */ | 1229 | */ |
1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1230 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1275 | wl1271_info("psm enabled"); | 1231 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1232 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1277 | true); | 1233 | true); |
1278 | } | 1234 | } |
1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1235 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1236 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1281 | wl1271_info("psm disabled"); | 1237 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
1282 | 1238 | ||
1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1239 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1284 | 1240 | ||
@@ -1310,11 +1266,11 @@ struct wl1271_filter_params { | |||
1310 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; | 1266 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; |
1311 | }; | 1267 | }; |
1312 | 1268 | ||
1313 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | 1269 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, |
1314 | struct dev_addr_list *mc_list) | 1270 | struct netdev_hw_addr_list *mc_list) |
1315 | { | 1271 | { |
1316 | struct wl1271_filter_params *fp; | 1272 | struct wl1271_filter_params *fp; |
1317 | int i; | 1273 | struct netdev_hw_addr *ha; |
1318 | 1274 | ||
1319 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1275 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1320 | if (!fp) { | 1276 | if (!fp) { |
@@ -1323,21 +1279,16 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | |||
1323 | } | 1279 | } |
1324 | 1280 | ||
1325 | /* update multicast filtering parameters */ | 1281 | /* update multicast filtering parameters */ |
1326 | fp->enabled = true; | ||
1327 | if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { | ||
1328 | mc_count = 0; | ||
1329 | fp->enabled = false; | ||
1330 | } | ||
1331 | |||
1332 | fp->mc_list_length = 0; | 1282 | fp->mc_list_length = 0; |
1333 | for (i = 0; i < mc_count; i++) { | 1283 | if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { |
1334 | if (mc_list->da_addrlen == ETH_ALEN) { | 1284 | fp->enabled = false; |
1285 | } else { | ||
1286 | fp->enabled = true; | ||
1287 | netdev_hw_addr_list_for_each(ha, mc_list) { | ||
1335 | memcpy(fp->mc_list[fp->mc_list_length], | 1288 | memcpy(fp->mc_list[fp->mc_list_length], |
1336 | mc_list->da_addr, ETH_ALEN); | 1289 | ha->addr, ETH_ALEN); |
1337 | fp->mc_list_length++; | 1290 | fp->mc_list_length++; |
1338 | } else | 1291 | } |
1339 | wl1271_warning("Unknown mc address length."); | ||
1340 | mc_list = mc_list->next; | ||
1341 | } | 1292 | } |
1342 | 1293 | ||
1343 | return (u64)(unsigned long)fp; | 1294 | return (u64)(unsigned long)fp; |
@@ -1381,14 +1332,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1381 | if (ret < 0) | 1332 | if (ret < 0) |
1382 | goto out_sleep; | 1333 | goto out_sleep; |
1383 | 1334 | ||
1384 | kfree(fp); | ||
1385 | |||
1386 | /* FIXME: We still need to set our filters properly */ | ||
1387 | |||
1388 | /* determine, whether supported filter values have changed */ | 1335 | /* determine, whether supported filter values have changed */ |
1389 | if (changed == 0) | 1336 | if (changed == 0) |
1390 | goto out_sleep; | 1337 | goto out_sleep; |
1391 | 1338 | ||
1339 | /* configure filters */ | ||
1340 | wl->filters = *total; | ||
1341 | wl1271_configure_filters(wl, 0); | ||
1342 | |||
1392 | /* apply configured filters */ | 1343 | /* apply configured filters */ |
1393 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | 1344 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
1394 | if (ret < 0) | 1345 | if (ret < 0) |
@@ -1399,6 +1350,7 @@ out_sleep: | |||
1399 | 1350 | ||
1400 | out: | 1351 | out: |
1401 | mutex_unlock(&wl->mutex); | 1352 | mutex_unlock(&wl->mutex); |
1353 | kfree(fp); | ||
1402 | } | 1354 | } |
1403 | 1355 | ||
1404 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1356 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -1449,15 +1401,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1449 | key_type = KEY_TKIP; | 1401 | key_type = KEY_TKIP; |
1450 | 1402 | ||
1451 | key_conf->hw_key_idx = key_conf->keyidx; | 1403 | key_conf->hw_key_idx = key_conf->keyidx; |
1452 | tx_seq_32 = wl->tx_security_seq_32; | 1404 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1453 | tx_seq_16 = wl->tx_security_seq_16; | 1405 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1454 | break; | 1406 | break; |
1455 | case ALG_CCMP: | 1407 | case ALG_CCMP: |
1456 | key_type = KEY_AES; | 1408 | key_type = KEY_AES; |
1457 | 1409 | ||
1458 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1410 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1459 | tx_seq_32 = wl->tx_security_seq_32; | 1411 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1460 | tx_seq_16 = wl->tx_security_seq_16; | 1412 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1461 | break; | 1413 | break; |
1462 | default: | 1414 | default: |
1463 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1415 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -1544,10 +1496,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1544 | goto out; | 1496 | goto out; |
1545 | 1497 | ||
1546 | if (wl1271_11a_enabled()) | 1498 | if (wl1271_11a_enabled()) |
1547 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1499 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1500 | req->ie, req->ie_len, 1, 0, | ||
1548 | WL1271_SCAN_BAND_DUAL, 3); | 1501 | WL1271_SCAN_BAND_DUAL, 3); |
1549 | else | 1502 | else |
1550 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1503 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1504 | req->ie, req->ie_len, 1, 0, | ||
1551 | WL1271_SCAN_BAND_2_4_GHZ, 3); | 1505 | WL1271_SCAN_BAND_2_4_GHZ, 3); |
1552 | 1506 | ||
1553 | wl1271_ps_elp_sleep(wl); | 1507 | wl1271_ps_elp_sleep(wl); |
@@ -1660,14 +1614,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1660 | * and enable the BSSID filter | 1614 | * and enable the BSSID filter |
1661 | */ | 1615 | */ |
1662 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 1616 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1663 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1664 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 1617 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1618 | |||
1665 | ret = wl1271_cmd_build_null_data(wl); | 1619 | ret = wl1271_cmd_build_null_data(wl); |
1666 | if (ret < 0) { | 1620 | if (ret < 0) |
1667 | wl1271_warning("cmd buld null data failed %d", | ||
1668 | ret); | ||
1669 | goto out_sleep; | 1621 | goto out_sleep; |
1670 | } | 1622 | |
1623 | /* filter out all packets not from this BSSID */ | ||
1624 | wl1271_configure_filters(wl, 0); | ||
1671 | 1625 | ||
1672 | /* Need to update the BSSID (for filtering etc) */ | 1626 | /* Need to update the BSSID (for filtering etc) */ |
1673 | do_join = true; | 1627 | do_join = true; |
@@ -1738,7 +1692,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1738 | } | 1692 | } |
1739 | 1693 | ||
1740 | if (do_join) { | 1694 | if (do_join) { |
1741 | ret = wl1271_cmd_join(wl); | 1695 | ret = wl1271_cmd_join(wl, wl->bss_type); |
1742 | if (ret < 0) { | 1696 | if (ret < 0) { |
1743 | wl1271_warning("cmd join failed %d", ret); | 1697 | wl1271_warning("cmd join failed %d", ret); |
1744 | goto out_sleep; | 1698 | goto out_sleep; |
@@ -1757,6 +1711,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1757 | const struct ieee80211_tx_queue_params *params) | 1711 | const struct ieee80211_tx_queue_params *params) |
1758 | { | 1712 | { |
1759 | struct wl1271 *wl = hw->priv; | 1713 | struct wl1271 *wl = hw->priv; |
1714 | u8 ps_scheme; | ||
1760 | int ret; | 1715 | int ret; |
1761 | 1716 | ||
1762 | mutex_lock(&wl->mutex); | 1717 | mutex_lock(&wl->mutex); |
@@ -1767,17 +1722,22 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1767 | if (ret < 0) | 1722 | if (ret < 0) |
1768 | goto out; | 1723 | goto out; |
1769 | 1724 | ||
1725 | /* the txop is confed in units of 32us by the mac80211, we need us */ | ||
1770 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 1726 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
1771 | params->cw_min, params->cw_max, | 1727 | params->cw_min, params->cw_max, |
1772 | params->aifs, params->txop); | 1728 | params->aifs, params->txop << 5); |
1773 | if (ret < 0) | 1729 | if (ret < 0) |
1774 | goto out_sleep; | 1730 | goto out_sleep; |
1775 | 1731 | ||
1732 | if (params->uapsd) | ||
1733 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | ||
1734 | else | ||
1735 | ps_scheme = CONF_PS_SCHEME_LEGACY; | ||
1736 | |||
1776 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 1737 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), |
1777 | CONF_CHANNEL_TYPE_EDCF, | 1738 | CONF_CHANNEL_TYPE_EDCF, |
1778 | wl1271_tx_get_queue(queue), | 1739 | wl1271_tx_get_queue(queue), |
1779 | CONF_PS_SCHEME_LEGACY_PSPOLL, | 1740 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); |
1780 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1781 | if (ret < 0) | 1741 | if (ret < 0) |
1782 | goto out_sleep; | 1742 | goto out_sleep; |
1783 | 1743 | ||
@@ -1947,7 +1907,6 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1947 | .add_interface = wl1271_op_add_interface, | 1907 | .add_interface = wl1271_op_add_interface, |
1948 | .remove_interface = wl1271_op_remove_interface, | 1908 | .remove_interface = wl1271_op_remove_interface, |
1949 | .config = wl1271_op_config, | 1909 | .config = wl1271_op_config, |
1950 | /* .config_interface = wl1271_op_config_interface, */ | ||
1951 | .prepare_multicast = wl1271_op_prepare_multicast, | 1910 | .prepare_multicast = wl1271_op_prepare_multicast, |
1952 | .configure_filter = wl1271_op_configure_filter, | 1911 | .configure_filter = wl1271_op_configure_filter, |
1953 | .tx = wl1271_op_tx, | 1912 | .tx = wl1271_op_tx, |
@@ -1959,7 +1918,69 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 1918 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1960 | }; | 1919 | }; |
1961 | 1920 | ||
1962 | static int wl1271_register_hw(struct wl1271 *wl) | 1921 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, |
1922 | struct device_attribute *attr, | ||
1923 | char *buf) | ||
1924 | { | ||
1925 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
1926 | ssize_t len; | ||
1927 | |||
1928 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
1929 | len = 500; | ||
1930 | |||
1931 | mutex_lock(&wl->mutex); | ||
1932 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | ||
1933 | wl->sg_enabled); | ||
1934 | mutex_unlock(&wl->mutex); | ||
1935 | |||
1936 | return len; | ||
1937 | |||
1938 | } | ||
1939 | |||
1940 | static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | ||
1941 | struct device_attribute *attr, | ||
1942 | const char *buf, size_t count) | ||
1943 | { | ||
1944 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
1945 | unsigned long res; | ||
1946 | int ret; | ||
1947 | |||
1948 | ret = strict_strtoul(buf, 10, &res); | ||
1949 | |||
1950 | if (ret < 0) { | ||
1951 | wl1271_warning("incorrect value written to bt_coex_mode"); | ||
1952 | return count; | ||
1953 | } | ||
1954 | |||
1955 | mutex_lock(&wl->mutex); | ||
1956 | |||
1957 | res = !!res; | ||
1958 | |||
1959 | if (res == wl->sg_enabled) | ||
1960 | goto out; | ||
1961 | |||
1962 | wl->sg_enabled = res; | ||
1963 | |||
1964 | if (wl->state == WL1271_STATE_OFF) | ||
1965 | goto out; | ||
1966 | |||
1967 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1968 | if (ret < 0) | ||
1969 | goto out; | ||
1970 | |||
1971 | wl1271_acx_sg_enable(wl, wl->sg_enabled); | ||
1972 | wl1271_ps_elp_sleep(wl); | ||
1973 | |||
1974 | out: | ||
1975 | mutex_unlock(&wl->mutex); | ||
1976 | return count; | ||
1977 | } | ||
1978 | |||
1979 | static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, | ||
1980 | wl1271_sysfs_show_bt_coex_state, | ||
1981 | wl1271_sysfs_store_bt_coex_state); | ||
1982 | |||
1983 | int wl1271_register_hw(struct wl1271 *wl) | ||
1963 | { | 1984 | { |
1964 | int ret; | 1985 | int ret; |
1965 | 1986 | ||
@@ -1980,8 +2001,17 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1980 | 2001 | ||
1981 | return 0; | 2002 | return 0; |
1982 | } | 2003 | } |
2004 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
1983 | 2005 | ||
1984 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 2006 | void wl1271_unregister_hw(struct wl1271 *wl) |
2007 | { | ||
2008 | ieee80211_unregister_hw(wl->hw); | ||
2009 | wl->mac80211_registered = false; | ||
2010 | |||
2011 | } | ||
2012 | EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | ||
2013 | |||
2014 | int wl1271_init_ieee80211(struct wl1271 *wl) | ||
1985 | { | 2015 | { |
1986 | /* The tx descriptor buffer and the TKIP space. */ | 2016 | /* The tx descriptor buffer and the TKIP space. */ |
1987 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2017 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
@@ -1994,7 +2024,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1994 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2024 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1995 | IEEE80211_HW_NOISE_DBM | | 2025 | IEEE80211_HW_NOISE_DBM | |
1996 | IEEE80211_HW_BEACON_FILTER | | 2026 | IEEE80211_HW_BEACON_FILTER | |
1997 | IEEE80211_HW_SUPPORTS_PS; | 2027 | IEEE80211_HW_SUPPORTS_PS | |
2028 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
2029 | IEEE80211_HW_HAS_RATE_CONTROL; | ||
1998 | 2030 | ||
1999 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2031 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2000 | BIT(NL80211_IFTYPE_ADHOC); | 2032 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2004,46 +2036,47 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2004 | if (wl1271_11a_enabled()) | 2036 | if (wl1271_11a_enabled()) |
2005 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2037 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2006 | 2038 | ||
2007 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 2039 | wl->hw->queues = 4; |
2008 | |||
2009 | return 0; | ||
2010 | } | ||
2011 | 2040 | ||
2012 | static void wl1271_device_release(struct device *dev) | 2041 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2013 | { | ||
2014 | 2042 | ||
2043 | return 0; | ||
2015 | } | 2044 | } |
2016 | 2045 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | |
2017 | static struct platform_device wl1271_device = { | ||
2018 | .name = "wl1271", | ||
2019 | .id = -1, | ||
2020 | |||
2021 | /* device model insists to have a release function */ | ||
2022 | .dev = { | ||
2023 | .release = wl1271_device_release, | ||
2024 | }, | ||
2025 | }; | ||
2026 | 2046 | ||
2027 | #define WL1271_DEFAULT_CHANNEL 0 | 2047 | #define WL1271_DEFAULT_CHANNEL 0 |
2028 | 2048 | ||
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 2049 | struct ieee80211_hw *wl1271_alloc_hw(void) |
2030 | { | 2050 | { |
2031 | struct ieee80211_hw *hw; | 2051 | struct ieee80211_hw *hw; |
2052 | struct platform_device *plat_dev = NULL; | ||
2032 | struct wl1271 *wl; | 2053 | struct wl1271 *wl; |
2033 | int i; | 2054 | int i, ret; |
2055 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
2034 | 2056 | ||
2035 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2057 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2036 | if (!hw) { | 2058 | if (!hw) { |
2037 | wl1271_error("could not alloc ieee80211_hw"); | 2059 | wl1271_error("could not alloc ieee80211_hw"); |
2038 | return ERR_PTR(-ENOMEM); | 2060 | ret = -ENOMEM; |
2061 | goto err_hw_alloc; | ||
2039 | } | 2062 | } |
2040 | 2063 | ||
2064 | plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); | ||
2065 | if (!plat_dev) { | ||
2066 | wl1271_error("could not allocate platform_device"); | ||
2067 | ret = -ENOMEM; | ||
2068 | goto err_plat_alloc; | ||
2069 | } | ||
2070 | |||
2071 | memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); | ||
2072 | |||
2041 | wl = hw->priv; | 2073 | wl = hw->priv; |
2042 | memset(wl, 0, sizeof(*wl)); | 2074 | memset(wl, 0, sizeof(*wl)); |
2043 | 2075 | ||
2044 | INIT_LIST_HEAD(&wl->list); | 2076 | INIT_LIST_HEAD(&wl->list); |
2045 | 2077 | ||
2046 | wl->hw = hw; | 2078 | wl->hw = hw; |
2079 | wl->plat_dev = plat_dev; | ||
2047 | 2080 | ||
2048 | skb_queue_head_init(&wl->tx_queue); | 2081 | skb_queue_head_init(&wl->tx_queue); |
2049 | 2082 | ||
@@ -2061,6 +2094,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2061 | wl->band = IEEE80211_BAND_2GHZ; | 2094 | wl->band = IEEE80211_BAND_2GHZ; |
2062 | wl->vif = NULL; | 2095 | wl->vif = NULL; |
2063 | wl->flags = 0; | 2096 | wl->flags = 0; |
2097 | wl->sg_enabled = true; | ||
2064 | 2098 | ||
2065 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2099 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
2066 | wl->tx_frames[i] = NULL; | 2100 | wl->tx_frames[i] = NULL; |
@@ -2070,15 +2104,55 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2070 | wl->state = WL1271_STATE_OFF; | 2104 | wl->state = WL1271_STATE_OFF; |
2071 | mutex_init(&wl->mutex); | 2105 | mutex_init(&wl->mutex); |
2072 | 2106 | ||
2107 | /* | ||
2108 | * FIXME: we should use a zero MAC address here, but for now we | ||
2109 | * generate a random Nokia address. | ||
2110 | */ | ||
2111 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
2112 | get_random_bytes(wl->mac_addr + 3, 3); | ||
2113 | |||
2073 | /* Apply default driver configuration. */ | 2114 | /* Apply default driver configuration. */ |
2074 | wl1271_conf_init(wl); | 2115 | wl1271_conf_init(wl); |
2075 | 2116 | ||
2117 | wl1271_debugfs_init(wl); | ||
2118 | |||
2119 | /* Register platform device */ | ||
2120 | ret = platform_device_register(wl->plat_dev); | ||
2121 | if (ret) { | ||
2122 | wl1271_error("couldn't register platform device"); | ||
2123 | goto err_hw; | ||
2124 | } | ||
2125 | dev_set_drvdata(&wl->plat_dev->dev, wl); | ||
2126 | |||
2127 | /* Create sysfs file to control bt coex state */ | ||
2128 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
2129 | if (ret < 0) { | ||
2130 | wl1271_error("failed to create sysfs file bt_coex_state"); | ||
2131 | goto err_platform; | ||
2132 | } | ||
2133 | |||
2076 | return hw; | 2134 | return hw; |
2135 | |||
2136 | err_platform: | ||
2137 | platform_device_unregister(wl->plat_dev); | ||
2138 | |||
2139 | err_hw: | ||
2140 | wl1271_debugfs_exit(wl); | ||
2141 | kfree(plat_dev); | ||
2142 | |||
2143 | err_plat_alloc: | ||
2144 | ieee80211_free_hw(hw); | ||
2145 | |||
2146 | err_hw_alloc: | ||
2147 | |||
2148 | return ERR_PTR(ret); | ||
2077 | } | 2149 | } |
2150 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
2078 | 2151 | ||
2079 | int wl1271_free_hw(struct wl1271 *wl) | 2152 | int wl1271_free_hw(struct wl1271 *wl) |
2080 | { | 2153 | { |
2081 | ieee80211_unregister_hw(wl->hw); | 2154 | platform_device_unregister(wl->plat_dev); |
2155 | kfree(wl->plat_dev); | ||
2082 | 2156 | ||
2083 | wl1271_debugfs_exit(wl); | 2157 | wl1271_debugfs_exit(wl); |
2084 | 2158 | ||
@@ -2095,145 +2169,8 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2095 | 2169 | ||
2096 | return 0; | 2170 | return 0; |
2097 | } | 2171 | } |
2098 | 2172 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | |
2099 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2100 | { | ||
2101 | struct wl12xx_platform_data *pdata; | ||
2102 | struct ieee80211_hw *hw; | ||
2103 | struct wl1271 *wl; | ||
2104 | int ret; | ||
2105 | |||
2106 | pdata = spi->dev.platform_data; | ||
2107 | if (!pdata) { | ||
2108 | wl1271_error("no platform data"); | ||
2109 | return -ENODEV; | ||
2110 | } | ||
2111 | |||
2112 | hw = wl1271_alloc_hw(); | ||
2113 | if (IS_ERR(hw)) | ||
2114 | return PTR_ERR(hw); | ||
2115 | |||
2116 | wl = hw->priv; | ||
2117 | |||
2118 | dev_set_drvdata(&spi->dev, wl); | ||
2119 | wl->spi = spi; | ||
2120 | |||
2121 | /* This is the only SPI value that we need to set here, the rest | ||
2122 | * comes from the board-peripherals file */ | ||
2123 | spi->bits_per_word = 32; | ||
2124 | |||
2125 | ret = spi_setup(spi); | ||
2126 | if (ret < 0) { | ||
2127 | wl1271_error("spi_setup failed"); | ||
2128 | goto out_free; | ||
2129 | } | ||
2130 | |||
2131 | wl->set_power = pdata->set_power; | ||
2132 | if (!wl->set_power) { | ||
2133 | wl1271_error("set power function missing in platform data"); | ||
2134 | ret = -ENODEV; | ||
2135 | goto out_free; | ||
2136 | } | ||
2137 | |||
2138 | wl->irq = spi->irq; | ||
2139 | if (wl->irq < 0) { | ||
2140 | wl1271_error("irq missing in platform data"); | ||
2141 | ret = -ENODEV; | ||
2142 | goto out_free; | ||
2143 | } | ||
2144 | |||
2145 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
2146 | if (ret < 0) { | ||
2147 | wl1271_error("request_irq() failed: %d", ret); | ||
2148 | goto out_free; | ||
2149 | } | ||
2150 | |||
2151 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
2152 | |||
2153 | disable_irq(wl->irq); | ||
2154 | |||
2155 | ret = platform_device_register(&wl1271_device); | ||
2156 | if (ret) { | ||
2157 | wl1271_error("couldn't register platform device"); | ||
2158 | goto out_irq; | ||
2159 | } | ||
2160 | dev_set_drvdata(&wl1271_device.dev, wl); | ||
2161 | |||
2162 | ret = wl1271_init_ieee80211(wl); | ||
2163 | if (ret) | ||
2164 | goto out_platform; | ||
2165 | |||
2166 | ret = wl1271_register_hw(wl); | ||
2167 | if (ret) | ||
2168 | goto out_platform; | ||
2169 | |||
2170 | wl1271_debugfs_init(wl); | ||
2171 | |||
2172 | wl1271_notice("initialized"); | ||
2173 | |||
2174 | return 0; | ||
2175 | |||
2176 | out_platform: | ||
2177 | platform_device_unregister(&wl1271_device); | ||
2178 | |||
2179 | out_irq: | ||
2180 | free_irq(wl->irq, wl); | ||
2181 | |||
2182 | out_free: | ||
2183 | ieee80211_free_hw(hw); | ||
2184 | |||
2185 | return ret; | ||
2186 | } | ||
2187 | |||
2188 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
2189 | { | ||
2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
2191 | |||
2192 | platform_device_unregister(&wl1271_device); | ||
2193 | free_irq(wl->irq, wl); | ||
2194 | |||
2195 | wl1271_free_hw(wl); | ||
2196 | |||
2197 | return 0; | ||
2198 | } | ||
2199 | |||
2200 | |||
2201 | static struct spi_driver wl1271_spi_driver = { | ||
2202 | .driver = { | ||
2203 | .name = "wl1271", | ||
2204 | .bus = &spi_bus_type, | ||
2205 | .owner = THIS_MODULE, | ||
2206 | }, | ||
2207 | |||
2208 | .probe = wl1271_probe, | ||
2209 | .remove = __devexit_p(wl1271_remove), | ||
2210 | }; | ||
2211 | |||
2212 | static int __init wl1271_init(void) | ||
2213 | { | ||
2214 | int ret; | ||
2215 | |||
2216 | ret = spi_register_driver(&wl1271_spi_driver); | ||
2217 | if (ret < 0) { | ||
2218 | wl1271_error("failed to register spi driver: %d", ret); | ||
2219 | goto out; | ||
2220 | } | ||
2221 | |||
2222 | out: | ||
2223 | return ret; | ||
2224 | } | ||
2225 | |||
2226 | static void __exit wl1271_exit(void) | ||
2227 | { | ||
2228 | spi_unregister_driver(&wl1271_spi_driver); | ||
2229 | |||
2230 | wl1271_notice("unloaded"); | ||
2231 | } | ||
2232 | |||
2233 | module_init(wl1271_init); | ||
2234 | module_exit(wl1271_exit); | ||
2235 | 2173 | ||
2236 | MODULE_LICENSE("GPL"); | 2174 | MODULE_LICENSE("GPL"); |
2237 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2175 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2238 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2176 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
2239 | 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..5a04482b9353 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 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 6730f5b96e76..b824c6cc2cc5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "wl1271_acx.h" | 25 | #include "wl1271_acx.h" |
26 | #include "wl1271_reg.h" | 26 | #include "wl1271_reg.h" |
27 | #include "wl1271_rx.h" | 27 | #include "wl1271_rx.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_io.h" | 28 | #include "wl1271_io.h" |
30 | 29 | ||
31 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
@@ -160,6 +159,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
160 | u8 *buf; | 159 | u8 *buf; |
161 | u8 beacon = 0; | 160 | u8 beacon = 0; |
162 | 161 | ||
162 | /* | ||
163 | * In PLT mode we seem to get frames and mac80211 warns about them, | ||
164 | * workaround this by not retrieving them at all. | ||
165 | */ | ||
166 | if (unlikely(wl->state == WL1271_STATE_PLT)) | ||
167 | return; | ||
168 | |||
163 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 169 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
164 | if (!skb) { | 170 | if (!skb) { |
165 | wl1271_error("Couldn't allocate RX frame"); | 171 | wl1271_error("Couldn't allocate RX frame"); |
@@ -218,6 +224,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
218 | 224 | ||
219 | wl->rx_counter++; | 225 | wl->rx_counter++; |
220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 226 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
221 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
222 | } | 227 | } |
228 | |||
229 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
223 | } | 230 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c new file mode 100644 index 000000000000..3c03de74dbfc --- /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, %d 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, %d 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", | ||
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 67a82934f36e..f44b05a32b0d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -21,17 +21,68 @@ | |||
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 | 29 | ||
29 | #include "wl1271.h" | 30 | #include "wl1271.h" |
30 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 32 | #include "wl1271_io.h" |
33 | |||
34 | #include "wl1271_reg.h" | ||
35 | |||
36 | #define WSPI_CMD_READ 0x40000000 | ||
37 | #define WSPI_CMD_WRITE 0x00000000 | ||
38 | #define WSPI_CMD_FIXED 0x20000000 | ||
39 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
40 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
41 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
42 | |||
43 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
44 | |||
45 | #define WSPI_INIT_CMD_START 0x00 | ||
46 | #define WSPI_INIT_CMD_TX 0x40 | ||
47 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
48 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
49 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
50 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
51 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
52 | #define WSPI_INIT_CMD_IOD 0x40 | ||
53 | #define WSPI_INIT_CMD_IP 0x20 | ||
54 | #define WSPI_INIT_CMD_CS 0x10 | ||
55 | #define WSPI_INIT_CMD_WS 0x08 | ||
56 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
57 | #define WSPI_INIT_CMD_END 0x01 | ||
58 | |||
59 | #define WSPI_INIT_CMD_LEN 8 | ||
60 | |||
61 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
62 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
63 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
64 | |||
65 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) | ||
66 | { | ||
67 | return wl->if_priv; | ||
68 | } | ||
69 | |||
70 | static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) | ||
71 | { | ||
72 | return &(wl_to_spi(wl)->dev); | ||
73 | } | ||
32 | 74 | ||
75 | static void wl1271_spi_disable_interrupts(struct wl1271 *wl) | ||
76 | { | ||
77 | disable_irq(wl->irq); | ||
78 | } | ||
79 | |||
80 | static void wl1271_spi_enable_interrupts(struct wl1271 *wl) | ||
81 | { | ||
82 | enable_irq(wl->irq); | ||
83 | } | ||
33 | 84 | ||
34 | void wl1271_spi_reset(struct wl1271 *wl) | 85 | static void wl1271_spi_reset(struct wl1271 *wl) |
35 | { | 86 | { |
36 | u8 *cmd; | 87 | u8 *cmd; |
37 | struct spi_transfer t; | 88 | struct spi_transfer t; |
@@ -52,12 +103,12 @@ void wl1271_spi_reset(struct wl1271 *wl) | |||
52 | t.len = WSPI_INIT_CMD_LEN; | 103 | t.len = WSPI_INIT_CMD_LEN; |
53 | spi_message_add_tail(&t, &m); | 104 | spi_message_add_tail(&t, &m); |
54 | 105 | ||
55 | spi_sync(wl->spi, &m); | 106 | spi_sync(wl_to_spi(wl), &m); |
56 | 107 | ||
57 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 108 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
58 | } | 109 | } |
59 | 110 | ||
60 | void wl1271_spi_init(struct wl1271 *wl) | 111 | static void wl1271_spi_init(struct wl1271 *wl) |
61 | { | 112 | { |
62 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | 113 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; |
63 | struct spi_transfer t; | 114 | struct spi_transfer t; |
@@ -106,7 +157,7 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
106 | t.len = WSPI_INIT_CMD_LEN; | 157 | t.len = WSPI_INIT_CMD_LEN; |
107 | spi_message_add_tail(&t, &m); | 158 | spi_message_add_tail(&t, &m); |
108 | 159 | ||
109 | spi_sync(wl->spi, &m); | 160 | spi_sync(wl_to_spi(wl), &m); |
110 | 161 | ||
111 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 162 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
112 | } | 163 | } |
@@ -138,7 +189,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
138 | t[0].rx_buf = buf + (len - num_busy_bytes); | 189 | t[0].rx_buf = buf + (len - num_busy_bytes); |
139 | t[0].len = num_busy_bytes; | 190 | t[0].len = num_busy_bytes; |
140 | spi_message_add_tail(&t[0], &m); | 191 | spi_message_add_tail(&t[0], &m); |
141 | spi_sync(wl->spi, &m); | 192 | spi_sync(wl_to_spi(wl), &m); |
142 | return; | 193 | return; |
143 | } | 194 | } |
144 | } | 195 | } |
@@ -158,7 +209,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
158 | t[0].rx_buf = busy_buf; | 209 | t[0].rx_buf = busy_buf; |
159 | t[0].len = sizeof(u32); | 210 | t[0].len = sizeof(u32); |
160 | spi_message_add_tail(&t[0], &m); | 211 | spi_message_add_tail(&t[0], &m); |
161 | spi_sync(wl->spi, &m); | 212 | spi_sync(wl_to_spi(wl), &m); |
162 | 213 | ||
163 | if (*busy_buf & 0x1) { | 214 | if (*busy_buf & 0x1) { |
164 | spi_message_init(&m); | 215 | spi_message_init(&m); |
@@ -166,7 +217,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
166 | t[0].rx_buf = buf; | 217 | t[0].rx_buf = buf; |
167 | t[0].len = len; | 218 | t[0].len = len; |
168 | spi_message_add_tail(&t[0], &m); | 219 | spi_message_add_tail(&t[0], &m); |
169 | spi_sync(wl->spi, &m); | 220 | spi_sync(wl_to_spi(wl), &m); |
170 | return; | 221 | return; |
171 | } | 222 | } |
172 | } | 223 | } |
@@ -177,7 +228,7 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
177 | } | 228 | } |
178 | #endif | 229 | #endif |
179 | 230 | ||
180 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 231 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
181 | size_t len, bool fixed) | 232 | size_t len, bool fixed) |
182 | { | 233 | { |
183 | struct spi_transfer t[3]; | 234 | struct spi_transfer t[3]; |
@@ -212,7 +263,7 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
212 | t[2].len = len; | 263 | t[2].len = len; |
213 | spi_message_add_tail(&t[2], &m); | 264 | spi_message_add_tail(&t[2], &m); |
214 | 265 | ||
215 | spi_sync(wl->spi, &m); | 266 | spi_sync(wl_to_spi(wl), &m); |
216 | 267 | ||
217 | /* FIXME: Check busy words, removed due to SPI bug */ | 268 | /* FIXME: Check busy words, removed due to SPI bug */ |
218 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | 269 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) |
@@ -222,7 +273,7 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
222 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 273 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
223 | } | 274 | } |
224 | 275 | ||
225 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | 276 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
226 | size_t len, bool fixed) | 277 | size_t len, bool fixed) |
227 | { | 278 | { |
228 | struct spi_transfer t[2]; | 279 | struct spi_transfer t[2]; |
@@ -250,8 +301,181 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
250 | t[1].len = len; | 301 | t[1].len = len; |
251 | spi_message_add_tail(&t[1], &m); | 302 | spi_message_add_tail(&t[1], &m); |
252 | 303 | ||
253 | spi_sync(wl->spi, &m); | 304 | spi_sync(wl_to_spi(wl), &m); |
254 | 305 | ||
255 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 306 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
256 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 307 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
257 | } | 308 | } |
309 | |||
310 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
311 | { | ||
312 | struct wl1271 *wl; | ||
313 | unsigned long flags; | ||
314 | |||
315 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
316 | |||
317 | wl = cookie; | ||
318 | |||
319 | /* complete the ELP completion */ | ||
320 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
321 | if (wl->elp_compl) { | ||
322 | complete(wl->elp_compl); | ||
323 | wl->elp_compl = NULL; | ||
324 | } | ||
325 | |||
326 | if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) | ||
327 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
328 | set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); | ||
329 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
330 | |||
331 | return IRQ_HANDLED; | ||
332 | } | ||
333 | |||
334 | static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) | ||
335 | { | ||
336 | if (wl->set_power) | ||
337 | wl->set_power(enable); | ||
338 | } | ||
339 | |||
340 | static struct wl1271_if_operations spi_ops = { | ||
341 | .read = wl1271_spi_raw_read, | ||
342 | .write = wl1271_spi_raw_write, | ||
343 | .reset = wl1271_spi_reset, | ||
344 | .init = wl1271_spi_init, | ||
345 | .power = wl1271_spi_set_power, | ||
346 | .dev = wl1271_spi_wl_to_dev, | ||
347 | .enable_irq = wl1271_spi_enable_interrupts, | ||
348 | .disable_irq = wl1271_spi_disable_interrupts | ||
349 | }; | ||
350 | |||
351 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
352 | { | ||
353 | struct wl12xx_platform_data *pdata; | ||
354 | struct ieee80211_hw *hw; | ||
355 | struct wl1271 *wl; | ||
356 | int ret; | ||
357 | |||
358 | pdata = spi->dev.platform_data; | ||
359 | if (!pdata) { | ||
360 | wl1271_error("no platform data"); | ||
361 | return -ENODEV; | ||
362 | } | ||
363 | |||
364 | hw = wl1271_alloc_hw(); | ||
365 | if (IS_ERR(hw)) | ||
366 | return PTR_ERR(hw); | ||
367 | |||
368 | wl = hw->priv; | ||
369 | |||
370 | dev_set_drvdata(&spi->dev, wl); | ||
371 | wl->if_priv = spi; | ||
372 | |||
373 | wl->if_ops = &spi_ops; | ||
374 | |||
375 | /* This is the only SPI value that we need to set here, the rest | ||
376 | * comes from the board-peripherals file */ | ||
377 | spi->bits_per_word = 32; | ||
378 | |||
379 | ret = spi_setup(spi); | ||
380 | if (ret < 0) { | ||
381 | wl1271_error("spi_setup failed"); | ||
382 | goto out_free; | ||
383 | } | ||
384 | |||
385 | wl->set_power = pdata->set_power; | ||
386 | if (!wl->set_power) { | ||
387 | wl1271_error("set power function missing in platform data"); | ||
388 | ret = -ENODEV; | ||
389 | goto out_free; | ||
390 | } | ||
391 | |||
392 | wl->irq = spi->irq; | ||
393 | if (wl->irq < 0) { | ||
394 | wl1271_error("irq missing in platform data"); | ||
395 | ret = -ENODEV; | ||
396 | goto out_free; | ||
397 | } | ||
398 | |||
399 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
400 | if (ret < 0) { | ||
401 | wl1271_error("request_irq() failed: %d", ret); | ||
402 | goto out_free; | ||
403 | } | ||
404 | |||
405 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
406 | |||
407 | disable_irq(wl->irq); | ||
408 | |||
409 | ret = wl1271_init_ieee80211(wl); | ||
410 | if (ret) | ||
411 | goto out_irq; | ||
412 | |||
413 | ret = wl1271_register_hw(wl); | ||
414 | if (ret) | ||
415 | goto out_irq; | ||
416 | |||
417 | wl1271_notice("initialized"); | ||
418 | |||
419 | return 0; | ||
420 | |||
421 | out_irq: | ||
422 | free_irq(wl->irq, wl); | ||
423 | |||
424 | out_free: | ||
425 | wl1271_free_hw(wl); | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
431 | { | ||
432 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
433 | |||
434 | free_irq(wl->irq, wl); | ||
435 | |||
436 | wl1271_unregister_hw(wl); | ||
437 | wl1271_free_hw(wl); | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | |||
443 | static struct spi_driver wl1271_spi_driver = { | ||
444 | .driver = { | ||
445 | .name = "wl1271", | ||
446 | .bus = &spi_bus_type, | ||
447 | .owner = THIS_MODULE, | ||
448 | }, | ||
449 | |||
450 | .probe = wl1271_probe, | ||
451 | .remove = __devexit_p(wl1271_remove), | ||
452 | }; | ||
453 | |||
454 | static int __init wl1271_init(void) | ||
455 | { | ||
456 | int ret; | ||
457 | |||
458 | ret = spi_register_driver(&wl1271_spi_driver); | ||
459 | if (ret < 0) { | ||
460 | wl1271_error("failed to register spi driver: %d", ret); | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | out: | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | static void __exit wl1271_exit(void) | ||
469 | { | ||
470 | spi_unregister_driver(&wl1271_spi_driver); | ||
471 | |||
472 | wl1271_notice("unloaded"); | ||
473 | } | ||
474 | |||
475 | module_init(wl1271_init); | ||
476 | module_exit(wl1271_exit); | ||
477 | |||
478 | MODULE_LICENSE("GPL"); | ||
479 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||
480 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
481 | 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 3919102e942e..2401e6035d51 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <net/genetlink.h> | 25 | #include <net/genetlink.h> |
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
30 | 29 | ||
31 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | 30 | #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..6d109df9a0a0 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)", |
@@ -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,10 @@ 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; |
313 | 307 | ||
314 | /* check for id legality */ | 308 | /* check for id legality */ |
315 | if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { | 309 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
316 | wl1271_warning("TX result illegal id: %d", id); | 310 | wl1271_warning("TX result illegal id: %d", id); |
317 | return; | 311 | return; |
318 | } | 312 | } |
@@ -336,15 +330,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
336 | wl->stats.retry_count += result->ack_failures; | 330 | wl->stats.retry_count += result->ack_failures; |
337 | 331 | ||
338 | /* update security sequence number */ | 332 | /* update security sequence number */ |
339 | seq = wl->tx_security_seq_16 + | 333 | wl->tx_security_seq += (result->lsb_security_sequence_number - |
340 | (result->lsb_security_sequence_number - | 334 | wl->tx_security_last_seq); |
341 | wl->tx_security_last_seq); | ||
342 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 335 | wl->tx_security_last_seq = result->lsb_security_sequence_number; |
343 | 336 | ||
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 */ | 337 | /* remove private header from packet */ |
349 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 338 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
350 | 339 | ||
@@ -361,29 +350,37 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
361 | result->id, skb, result->ack_failures, | 350 | result->id, skb, result->ack_failures, |
362 | result->rate_class_index, result->status); | 351 | result->rate_class_index, result->status); |
363 | 352 | ||
353 | /* FIXME: do we need to tell the stack about the used rate? */ | ||
354 | |||
364 | /* return the packet to the stack */ | 355 | /* return the packet to the stack */ |
365 | ieee80211_tx_status(wl->hw, skb); | 356 | ieee80211_tx_status(wl->hw, skb); |
366 | wl->tx_frames[result->id] = NULL; | 357 | wl->tx_frames[result->id] = NULL; |
367 | } | 358 | } |
368 | 359 | ||
369 | /* Called upon reception of a TX complete interrupt */ | 360 | /* Called upon reception of a TX complete interrupt */ |
370 | void wl1271_tx_complete(struct wl1271 *wl, u32 count) | 361 | void wl1271_tx_complete(struct wl1271 *wl) |
371 | { | 362 | { |
372 | struct wl1271_acx_mem_map *memmap = | 363 | struct wl1271_acx_mem_map *memmap = |
373 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 364 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
365 | u32 count, fw_counter; | ||
374 | u32 i; | 366 | u32 i; |
375 | 367 | ||
376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
377 | |||
378 | /* read the tx results from the chipset */ | 368 | /* read the tx results from the chipset */ |
379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 369 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 370 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
371 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | ||
372 | |||
373 | /* write host counter to chipset (to ack) */ | ||
374 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | ||
375 | offsetof(struct wl1271_tx_hw_res_if, | ||
376 | tx_result_host_counter), fw_counter); | ||
377 | |||
378 | count = fw_counter - wl->tx_results_count; | ||
379 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
381 | 380 | ||
382 | /* verify that the result buffer is not getting overrun */ | 381 | /* verify that the result buffer is not getting overrun */ |
383 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 382 | if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) |
384 | wl1271_warning("TX result overflow from chipset: %d", count); | 383 | wl1271_warning("TX result overflow from chipset: %d", count); |
385 | count = TX_HW_RESULT_QUEUE_LEN; | ||
386 | } | ||
387 | 384 | ||
388 | /* process the results */ | 385 | /* process the results */ |
389 | for (i = 0; i < count; i++) { | 386 | for (i = 0; i < count; i++) { |
@@ -397,11 +394,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
397 | wl->tx_results_count++; | 394 | wl->tx_results_count++; |
398 | } | 395 | } |
399 | 396 | ||
400 | /* write host counter to chipset (to ack) */ | 397 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 398 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
402 | offsetof(struct wl1271_tx_hw_res_if, | 399 | unsigned long flags; |
403 | tx_result_host_counter), | 400 | |
404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 401 | /* firmware buffer has space, restart queues */ |
402 | wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); | ||
403 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
404 | ieee80211_wake_queues(wl->hw); | ||
405 | clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
406 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
407 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
408 | } | ||
405 | } | 409 | } |
406 | 410 | ||
407 | /* caller must hold wl->mutex */ | 411 | /* caller must hold wl->mutex */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 17e405a09caa..5e6c27a57415 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,7 @@ 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); |
165 | 162 | ||
166 | #endif | 163 | #endif |