kernel-power git -> kernel-bfs
[kernel-bfs] / kernel-bfs-2.6.28 / debian / patches / wl1251-monitor-mode.diff
1 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_cmd.c
2 ===================================================================
3 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_cmd.c   2010-05-14 23:59:06.832141497 +0200
4 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_cmd.c        2010-05-14 23:59:07.524273985 +0200
5 @@ -204,11 +204,11 @@
6         return 0;
7  }
8  
9 -int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
10 +int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable)
11  {
12         struct cmd_enabledisable_path *cmd;
13         int ret;
14 -       u16 cmd_rx, cmd_tx;
15 +       u16 cmd_rx;
16  
17         wl1251_debug(DEBUG_CMD, "cmd data path");
18  
19 @@ -222,10 +222,8 @@
20  
21         if (enable) {
22                 cmd_rx = CMD_ENABLE_RX;
23 -               cmd_tx = CMD_ENABLE_TX;
24         } else {
25                 cmd_rx = CMD_DISABLE_RX;
26 -               cmd_tx = CMD_DISABLE_TX;
27         }
28  
29         ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
30 @@ -238,6 +236,33 @@
31         wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
32                      enable ? "start" : "stop", channel);
33  
34 +out:
35 +       kfree(cmd);
36 +       return ret;
37 +}
38 +
39 +int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
40 +{
41 +       struct cmd_enabledisable_path *cmd;
42 +       int ret;
43 +       u16 cmd_tx;
44 +
45 +       wl1251_debug(DEBUG_CMD, "cmd data path");
46 +
47 +       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
48 +       if (!cmd) {
49 +               ret = -ENOMEM;
50 +               goto out;
51 +       }
52 +
53 +       cmd->channel = channel;
54 +
55 +       if (enable) {
56 +               cmd_tx = CMD_ENABLE_TX;
57 +       } else {
58 +               cmd_tx = CMD_DISABLE_TX;
59 +       }
60 +
61         ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
62         if (ret < 0) {
63                 wl1251_error("tx %s cmd for channel %d failed",
64 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_cmd.h
65 ===================================================================
66 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_cmd.h   2010-05-14 23:59:06.832141497 +0200
67 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_cmd.h        2010-05-14 23:59:07.524273985 +0200
68 @@ -35,7 +35,8 @@
69  int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
70  int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
71                    void *bitmap, u16 bitmap_len, u8 bitmap_control);
72 -int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
73 +int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable);
74 +int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable);
75  int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
76                     u16 beacon_interval, u8 dtim_interval);
77  int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
78 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_init.c
79 ===================================================================
80 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_init.c  2010-05-14 23:59:07.063992150 +0200
81 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_init.c       2010-05-15 00:46:16.884045939 +0200
82 @@ -35,7 +35,7 @@
83  {
84         int ret;
85  
86 -       ret = wl1251_acx_feature_cfg(wl);
87 +       ret = wl1251_acx_feature_cfg(wl, DF_SNIFF_MODE_ENABLE);
88         if (ret < 0) {
89                 wl1251_warning("couldn't set feature config");
90                 return ret;
91 @@ -399,8 +399,13 @@
92         if (ret < 0)
93                 goto out_free_data_path;
94  
95 -       /* Enable data path */
96 -       ret = wl1251_cmd_data_path(wl, wl->channel, 1);
97 +       /* Enable rx data path */
98 +       ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
99 +       if (ret < 0)
100 +               goto out_free_data_path;
101 +
102 +       /* Enable tx data path */
103 +       ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1);
104         if (ret < 0)
105                 goto out_free_data_path;
106  
107 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_main.c
108 ===================================================================
109 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_main.c  2010-05-14 23:59:07.063992150 +0200
110 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_main.c       2010-05-15 03:33:55.871890108 +0200
111 @@ -667,7 +667,11 @@
112         if (ret < 0)
113                 return ret;
114  
115 -       ret = wl1251_cmd_data_path(wl, wl->channel, 1);
116 +       ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
117 +       if (ret < 0)
118 +               return ret;
119 +
120 +       ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1);
121         if (ret < 0)
122                 return ret;
123  
124 @@ -967,6 +971,12 @@
125                 goto out;
126         }
127  
128 +       ret = wl1251_acx_feature_cfg(wl, 0);
129 +       if (ret < 0) {
130 +               wl1251_warning("couldn't set feature config");
131 +               goto out;
132 +       }
133 +
134         wl->vif = conf->vif;
135  
136         switch (conf->type) {
137 @@ -998,10 +1008,19 @@
138                                          struct ieee80211_if_init_conf *conf)
139  {
140         struct wl1251 *wl = hw->priv;
141 +       int ret = 0;
142  
143         mutex_lock(&wl->mutex);
144 +
145         wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
146 +
147         wl->vif = NULL;
148 +
149 +       ret = wl1251_acx_feature_cfg(wl, DF_SNIFF_MODE_ENABLE);
150 +       if (ret < 0) {
151 +               wl1251_warning("couldn't set feature config");
152 +       }
153 +
154         mutex_unlock(&wl->mutex);
155  }
156  
157 @@ -1180,6 +1199,13 @@
158         if (ret < 0)
159                 goto out;
160  
161 +       /* Monitor mode */
162 +       if (wl->vif == NULL && wl->channel != channel) {
163 +               ret = wl1251_cmd_data_path_rx(wl, channel, 1);
164 +               if (ret < 0)
165 +                       goto out_sleep;
166 +       }
167 +
168         wl->channel = channel;
169  
170         if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
171 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_acx.c
172 ===================================================================
173 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_acx.c   2010-05-15 00:00:22.995807778 +0200
174 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_acx.c        2010-05-15 00:14:02.111891358 +0200
175 @@ -212,7 +212,7 @@
176         return ret;
177  }
178  
179 -int wl1251_acx_feature_cfg(struct wl1251 *wl)
180 +int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
181  {
182         struct acx_feature_config *feature;
183         int ret;
184 @@ -226,7 +226,7 @@
185         }
186  
187         /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
188 -       feature->data_flow_options = 0;
189 +       feature->data_flow_options = data_flow_options;
190         feature->options = 0;
191  
192         ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
193 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_acx.h
194 ===================================================================
195 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_acx.h   2010-05-15 00:01:16.660049057 +0200
196 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_acx.h        2010-05-15 00:14:27.776191658 +0200
197 @@ -1454,7 +1454,7 @@
198  int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
199  int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
200  int wl1251_acx_tx_power(struct wl1251 *wl, int power);
201 -int wl1251_acx_feature_cfg(struct wl1251 *wl);
202 +int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options);
203  int wl1251_acx_mem_map(struct wl1251 *wl,
204                        struct acx_header *mem_map, size_t len);
205  int wl1251_acx_data_path_params(struct wl1251 *wl,
206 Index: kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_rx.c
207 ===================================================================
208 --- kernel-power-2.6.28.orig/drivers/net/wireless/wl12xx/wl1251_rx.c    2010-05-16 15:04:08.279402004 +0200
209 +++ kernel-power-2.6.28/drivers/net/wireless/wl12xx/wl1251_rx.c 2010-05-16 18:56:57.075800531 +0200
210 @@ -100,7 +100,54 @@
211                 status->flag |= RX_FLAG_FAILED_FCS_CRC;
212  
213  
214 -       /* FIXME: set status->rate_idx */
215 +       switch (desc->rate) {
216 +               /* skip 1 and 12 Mbps because they have same value 0x0a */
217 +       case RATE_2MBPS:
218 +               status->rate_idx = 1;
219 +               break;
220 +       case RATE_5_5MBPS:
221 +               status->rate_idx = 2;
222 +               break;
223 +       case RATE_11MBPS:
224 +               status->rate_idx = 3;
225 +               break;
226 +       case RATE_6MBPS:
227 +               status->rate_idx = 4;
228 +               break;
229 +       case RATE_9MBPS:
230 +               status->rate_idx = 5;
231 +               break;
232 +       case RATE_18MBPS:
233 +               status->rate_idx = 7;
234 +               break;
235 +       case RATE_24MBPS:
236 +               status->rate_idx = 8;
237 +               break;
238 +       case RATE_36MBPS:
239 +               status->rate_idx = 9;
240 +               break;
241 +       case RATE_48MBPS:
242 +               status->rate_idx = 10;
243 +               break;
244 +       case RATE_54MBPS:
245 +               status->rate_idx = 11;
246 +               break;
247 +       }
248 +
249 +       /* for 1 and 12 Mbps we have to check the modulation */
250 +       if (desc->rate == RATE_1MBPS) {
251 +               if ((desc->mod_pre & OFDM_RATE_BIT) == 0) {
252 +                       /* CCK -> RATE_1MBPS*/
253 +                       status->rate_idx = 0;
254 +               } else {
255 +                       /* OFDM -> RATE_12MBPS */
256 +                       status->rate_idx = 6;
257 +               }
258 +       }
259 +
260 +       if ((desc->mod_pre & SHORT_PREAMBLE_BIT) != 0) {
261 +               status->flag |= RX_FLAG_SHORTPRE;
262 +       }
263  }
264  
265  static void wl1251_rx_body(struct wl1251 *wl,