aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/brcm80211/sys/wl_mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/brcm80211/sys/wl_mac80211.c')
-rw-r--r--drivers/staging/brcm80211/sys/wl_mac80211.c1026
1 files changed, 245 insertions, 781 deletions
diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c b/drivers/staging/brcm80211/sys/wl_mac80211.c
index d060377629a..bdd629d72a7 100644
--- a/drivers/staging/brcm80211/sys/wl_mac80211.c
+++ b/drivers/staging/brcm80211/sys/wl_mac80211.c
@@ -21,72 +21,36 @@
21#include <linux/string.h> 21#include <linux/string.h>
22#include <linux/pci_ids.h> 22#include <linux/pci_ids.h>
23#include <bcmdefs.h> 23#include <bcmdefs.h>
24#include <linuxver.h> 24#include <linux/module.h>
25#include <linux/pci.h>
26#include <linux/sched.h>
25#include <osl.h> 27#include <osl.h>
26#define WLC_MAXBSSCFG 1 /* single BSS configs */ 28#define WLC_MAXBSSCFG 1 /* single BSS configs */
27 29
28#include <wlc_cfg.h> 30#include <wlc_cfg.h>
29#include <net/mac80211.h> 31#include <net/mac80211.h>
30#include <epivers.h>
31#ifndef WLC_HIGH_ONLY
32#include <phy_version.h> 32#include <phy_version.h>
33#endif
34#include <bcmutils.h> 33#include <bcmutils.h>
35#include <pcicfg.h> 34#include <pcicfg.h>
36#include <wlioctl.h> 35#include <wlioctl.h>
37#include <wlc_key.h> 36#include <wlc_key.h>
37#include <sbhndpio.h>
38#include <sbhnddma.h>
38#include <wlc_channel.h> 39#include <wlc_channel.h>
39#include <wlc_pub.h> 40#include <wlc_pub.h>
40#include <wlc_scb.h> 41#include <wlc_scb.h>
41#include <wl_dbg.h> 42#include <wl_dbg.h>
42#ifdef BCMSDIO
43#include <bcmsdh.h>
44#endif
45#include <wl_export.h> 43#include <wl_export.h>
46#ifdef WLC_HIGH_ONLY
47#include "dbus.h"
48#include "bcm_rpc_tp.h"
49#include "bcm_rpc.h"
50#include "bcm_xdr.h"
51#include "wlc_rpc.h"
52#endif
53 44
54#include <wl_mac80211.h> 45#include <wl_mac80211.h>
55#include <linux/firmware.h> 46#include <linux/firmware.h>
56#ifndef WLC_HIGH_ONLY
57#include <wl_ucode.h> 47#include <wl_ucode.h>
58#include <d11ucode_ext.h> 48#include <d11ucode_ext.h>
59#endif
60 49
61#ifdef BCMSDIO
62extern struct device *sdiommc_dev;
63#endif
64
65extern void wlc_wme_setparams(wlc_info_t *wlc, u16 aci, void *arg,
66 bool suspend);
67bool wlc_sendpkt_mac80211(wlc_info_t *wlc, void *sdu, struct ieee80211_hw *hw);
68void wlc_mac_bcn_promisc_change(wlc_info_t *wlc, bool promisc);
69void wlc_set_addrmatch(wlc_info_t *wlc, int match_reg_offset,
70 const struct ether_addr *addr);
71 50
72static void wl_timer(unsigned long data); 51static void wl_timer(unsigned long data);
73static void _wl_timer(wl_timer_t *t); 52static void _wl_timer(wl_timer_t *t);
74 53
75#ifdef WLC_HIGH_ONLY
76#define RPCQ_LOCK(_wl, _flags) spin_lock_irqsave(&(_wl)->rpcq_lock, (_flags))
77#define RPCQ_UNLOCK(_wl, _flags) spin_unlock_irqrestore(&(_wl)->rpcq_lock, (_flags))
78#define TXQ_LOCK(_wl, _flags) spin_lock_irqsave(&(_wl)->txq_lock, (_flags))
79#define TXQ_UNLOCK(_wl, _flags) spin_unlock_irqrestore(&(_wl)->txq_lock, (_flags))
80static void wl_rpc_down(void *wlh);
81static void wl_rpcq_free(wl_info_t *wl);
82static void wl_rpcq_dispatch(struct wl_task *task);
83static void wl_rpc_dispatch_schedule(void *ctx, struct rpc_buf *buf);
84static void wl_start_txqwork(struct wl_task *task);
85static void wl_txq_free(wl_info_t *wl);
86static void wl_timer_task(wl_task_t *task);
87static int wl_schedule_task(wl_info_t *wl, void (*fn) (struct wl_task *),
88 void *context);
89#endif /* WLC_HIGH_ONLY */
90 54
91static int ieee_hw_init(struct ieee80211_hw *hw); 55static int ieee_hw_init(struct ieee80211_hw *hw);
92static int ieee_hw_rate_init(struct ieee80211_hw *hw); 56static int ieee_hw_rate_init(struct ieee80211_hw *hw);
@@ -134,16 +98,14 @@ struct ieee80211_tkip_data {
134 u8 rx_hdr[16], tx_hdr[16]; 98 u8 rx_hdr[16], tx_hdr[16];
135}; 99};
136 100
137#ifndef WLC_HIGH_ONLY 101#define WL_DEV_IF(dev) ((struct wl_if *)netdev_priv(dev))
138#define WL_DEV_IF(dev) ((wl_if_t *)netdev_priv(dev)) 102#define WL_INFO(dev) ((struct wl_info *)(WL_DEV_IF(dev)->wl))
139#define WL_INFO(dev) ((wl_info_t *)(WL_DEV_IF(dev)->wl)) /* points to wl */ 103static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev);
140static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev); 104static void wl_release_fw(struct wl_info *wl);
141static void wl_release_fw(wl_info_t *wl);
142#endif
143 105
144/* local prototypes */ 106/* local prototypes */
145static int wl_start(struct sk_buff *skb, wl_info_t *wl); 107static int wl_start(struct sk_buff *skb, struct wl_info *wl);
146static int wl_start_int(wl_info_t *wl, struct ieee80211_hw *hw, 108static int wl_start_int(struct wl_info *wl, struct ieee80211_hw *hw,
147 struct sk_buff *skb); 109 struct sk_buff *skb);
148static void wl_dpc(unsigned long data); 110static void wl_dpc(unsigned long data);
149 111
@@ -152,7 +114,6 @@ MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
152MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); 114MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
153MODULE_LICENSE("Dual BSD/GPL"); 115MODULE_LICENSE("Dual BSD/GPL");
154 116
155#ifndef BCMSDIO
156/* recognized PCI IDs */ 117/* recognized PCI IDs */
157static struct pci_device_id wl_id_table[] = { 118static struct pci_device_id wl_id_table[] = {
158 {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43225 2G */ 119 {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43225 2G */
@@ -163,55 +124,18 @@ static struct pci_device_id wl_id_table[] = {
163 124
164MODULE_DEVICE_TABLE(pci, wl_id_table); 125MODULE_DEVICE_TABLE(pci, wl_id_table);
165static void wl_remove(struct pci_dev *pdev); 126static void wl_remove(struct pci_dev *pdev);
166#endif /* !BCMSDIO */
167 127
168#ifdef BCMSDIO
169static uint sd_drivestrength = 6;
170module_param(sd_drivestrength, uint, 0);
171#endif
172 128
173#ifdef BCMDBG 129#ifdef BCMDBG
174static int msglevel = 0xdeadbeef; 130static int msglevel = 0xdeadbeef;
175module_param(msglevel, int, 0); 131module_param(msglevel, int, 0);
176#ifndef WLC_HIGH_ONLY
177static int phymsglevel = 0xdeadbeef; 132static int phymsglevel = 0xdeadbeef;
178module_param(phymsglevel, int, 0); 133module_param(phymsglevel, int, 0);
179#endif /* WLC_HIGH_ONLY */
180#endif /* BCMDBG */ 134#endif /* BCMDBG */
181 135
182static int oneonly;
183module_param(oneonly, int, 0);
184
185static int piomode;
186module_param(piomode, int, 0);
187
188static int instance_base; /* Starting instance number */
189module_param(instance_base, int, 0);
190
191#if defined(BCMDBG)
192static char *macaddr;
193module_param(macaddr, charp, S_IRUGO);
194#endif
195
196static int nompc = 1;
197module_param(nompc, int, 0);
198
199static char name[IFNAMSIZ] = "eth%d";
200module_param_string(name, name, IFNAMSIZ, 0);
201
202#ifndef SRCBASE
203#define SRCBASE "."
204#endif
205
206#define WL_MAGIC 0xdeadbeef
207
208#define HW_TO_WL(hw) (hw->priv) 136#define HW_TO_WL(hw) (hw->priv)
209#define WL_TO_HW(wl) (wl->pub->ieee_hw) 137#define WL_TO_HW(wl) (wl->pub->ieee_hw)
210#ifdef WLC_HIGH_ONLY
211static int wl_ops_tx_nl(struct ieee80211_hw *hw, struct sk_buff *skb);
212#else
213static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb); 138static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
214#endif
215static int wl_ops_start(struct ieee80211_hw *hw); 139static int wl_ops_start(struct ieee80211_hw *hw);
216static void wl_ops_stop(struct ieee80211_hw *hw); 140static void wl_ops_stop(struct ieee80211_hw *hw);
217static int wl_ops_add_interface(struct ieee80211_hw *hw, 141static int wl_ops_add_interface(struct ieee80211_hw *hw,
@@ -249,28 +173,13 @@ static int wl_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
249 enum ieee80211_ampdu_mlme_action action, 173 enum ieee80211_ampdu_mlme_action action,
250 struct ieee80211_sta *sta, u16 tid, u16 *ssn); 174 struct ieee80211_sta *sta, u16 tid, u16 *ssn);
251 175
252#ifdef WLC_HIGH_ONLY
253static int wl_ops_tx_nl(struct ieee80211_hw *hw, struct sk_buff *skb)
254{
255 int status;
256 wl_info_t *wl = hw->priv;
257 if (!wl->pub->up) {
258 WL_ERROR(("ops->tx called while down\n"));
259 status = -ENETDOWN;
260 goto done;
261 }
262 status = wl_start(skb, wl);
263 done:
264 return status;
265}
266#else
267static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 176static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
268{ 177{
269 int status; 178 int status;
270 wl_info_t *wl = hw->priv; 179 struct wl_info *wl = hw->priv;
271 WL_LOCK(wl); 180 WL_LOCK(wl);
272 if (!wl->pub->up) { 181 if (!wl->pub->up) {
273 WL_ERROR(("ops->tx called while down\n")); 182 WL_ERROR("ops->tx called while down\n");
274 status = -ENETDOWN; 183 status = -ENETDOWN;
275 goto done; 184 goto done;
276 } 185 }
@@ -279,13 +188,14 @@ static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
279 WL_UNLOCK(wl); 188 WL_UNLOCK(wl);
280 return status; 189 return status;
281} 190}
282#endif /* WLC_HIGH_ONLY */
283 191
284static int wl_ops_start(struct ieee80211_hw *hw) 192static int wl_ops_start(struct ieee80211_hw *hw)
285{ 193{
286 wl_info_t *wl = hw->priv; 194 struct wl_info *wl = hw->priv;
287 /* struct ieee80211_channel *curchan = hw->conf.channel; */ 195 /*
288 WL_NONE(("%s : Initial channel: %d\n", __func__, curchan->hw_value)); 196 struct ieee80211_channel *curchan = hw->conf.channel;
197 WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
198 */
289 199
290 WL_LOCK(wl); 200 WL_LOCK(wl);
291 ieee80211_wake_queues(hw); 201 ieee80211_wake_queues(hw);
@@ -296,7 +206,7 @@ static int wl_ops_start(struct ieee80211_hw *hw)
296 206
297static void wl_ops_stop(struct ieee80211_hw *hw) 207static void wl_ops_stop(struct ieee80211_hw *hw)
298{ 208{
299 wl_info_t *wl = hw->priv; 209 struct wl_info *wl = hw->priv;
300 ASSERT(wl); 210 ASSERT(wl);
301 WL_LOCK(wl); 211 WL_LOCK(wl);
302 wl_down(wl); 212 wl_down(wl);
@@ -309,7 +219,7 @@ static void wl_ops_stop(struct ieee80211_hw *hw)
309static int 219static int
310wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 220wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
311{ 221{
312 wl_info_t *wl; 222 struct wl_info *wl;
313 int err; 223 int err;
314 224
315 /* Just STA for now */ 225 /* Just STA for now */
@@ -318,8 +228,8 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
318 vif->type != NL80211_IFTYPE_STATION && 228 vif->type != NL80211_IFTYPE_STATION &&
319 vif->type != NL80211_IFTYPE_WDS && 229 vif->type != NL80211_IFTYPE_WDS &&
320 vif->type != NL80211_IFTYPE_ADHOC) { 230 vif->type != NL80211_IFTYPE_ADHOC) {
321 WL_ERROR(("%s: Attempt to add type %d, only STA for now\n", 231 WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
322 __func__, vif->type)); 232 __func__, vif->type);
323 return -EOPNOTSUPP; 233 return -EOPNOTSUPP;
324 } 234 }
325 235
@@ -329,7 +239,7 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
329 WL_UNLOCK(wl); 239 WL_UNLOCK(wl);
330 240
331 if (err != 0) 241 if (err != 0)
332 WL_ERROR(("%s: wl_up() returned %d\n", __func__, err)); 242 WL_ERROR("%s: wl_up() returned %d\n", __func__, err);
333 return err; 243 return err;
334} 244}
335 245
@@ -343,7 +253,7 @@ static int
343ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan, 253ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
344 enum nl80211_channel_type type) 254 enum nl80211_channel_type type)
345{ 255{
346 wl_info_t *wl = HW_TO_WL(hw); 256 struct wl_info *wl = HW_TO_WL(hw);
347 int err = 0; 257 int err = 0;
348 258
349 switch (type) { 259 switch (type) {
@@ -355,8 +265,7 @@ ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
355 break; 265 break;
356 case NL80211_CHAN_HT40MINUS: 266 case NL80211_CHAN_HT40MINUS:
357 case NL80211_CHAN_HT40PLUS: 267 case NL80211_CHAN_HT40PLUS:
358 WL_ERROR(("%s: Need to implement 40 Mhz Channels!\n", 268 WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__);
359 __func__));
360 break; 269 break;
361 } 270 }
362 271
@@ -368,17 +277,17 @@ ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
368static int wl_ops_config(struct ieee80211_hw *hw, u32 changed) 277static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
369{ 278{
370 struct ieee80211_conf *conf = &hw->conf; 279 struct ieee80211_conf *conf = &hw->conf;
371 wl_info_t *wl = HW_TO_WL(hw); 280 struct wl_info *wl = HW_TO_WL(hw);
372 int err = 0; 281 int err = 0;
373 int new_int; 282 int new_int;
374 283
375 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { 284 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
376 WL_NONE(("%s: Setting listen interval to %d\n", 285 WL_NONE("%s: Setting listen interval to %d\n",
377 __func__, conf->listen_interval)); 286 __func__, conf->listen_interval);
378 if (wlc_iovar_setint 287 if (wlc_iovar_setint
379 (wl->wlc, "bcn_li_bcn", conf->listen_interval)) { 288 (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
380 WL_ERROR(("%s: Error setting listen_interval\n", 289 WL_ERROR("%s: Error setting listen_interval\n",
381 __func__)); 290 __func__);
382 err = -EIO; 291 err = -EIO;
383 goto config_out; 292 goto config_out;
384 } 293 }
@@ -386,41 +295,42 @@ static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
386 ASSERT(new_int == conf->listen_interval); 295 ASSERT(new_int == conf->listen_interval);
387 } 296 }
388 if (changed & IEEE80211_CONF_CHANGE_MONITOR) 297 if (changed & IEEE80211_CONF_CHANGE_MONITOR)
389 WL_NONE(("Need to set monitor mode\n")); 298 WL_NONE("Need to set monitor mode\n");
390 if (changed & IEEE80211_CONF_CHANGE_PS) 299 if (changed & IEEE80211_CONF_CHANGE_PS)
391 WL_NONE(("Need to set Power-save mode\n")); 300 WL_NONE("Need to set Power-save mode\n");
392 301
393 if (changed & IEEE80211_CONF_CHANGE_POWER) { 302 if (changed & IEEE80211_CONF_CHANGE_POWER) {
394 WL_NONE(("%s: Setting tx power to %d dbm\n", __func__, 303 WL_NONE("%s: Setting tx power to %d dbm\n",
395 conf->power_level)); 304 __func__, conf->power_level);
396 if (wlc_iovar_setint 305 if (wlc_iovar_setint
397 (wl->wlc, "qtxpower", conf->power_level * 4)) { 306 (wl->wlc, "qtxpower", conf->power_level * 4)) {
398 WL_ERROR(("%s: Error setting power_level\n", __func__)); 307 WL_ERROR("%s: Error setting power_level\n", __func__);
399 err = -EIO; 308 err = -EIO;
400 goto config_out; 309 goto config_out;
401 } 310 }
402 wlc_iovar_getint(wl->wlc, "qtxpower", &new_int); 311 wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
403 if (new_int != (conf->power_level * 4)) 312 if (new_int != (conf->power_level * 4))
404 WL_ERROR(("%s: Power level req != actual, %d %d\n", 313 WL_ERROR("%s: Power level req != actual, %d %d\n",
405 __func__, conf->power_level * 4, new_int)); 314 __func__, conf->power_level * 4, new_int);
406 } 315 }
407 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 316 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
408 err = ieee_set_channel(hw, conf->channel, conf->channel_type); 317 err = ieee_set_channel(hw, conf->channel, conf->channel_type);
409 } 318 }
410 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { 319 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
411 WL_NONE(("%s: srl %d, lrl %d\n", __func__, 320 WL_NONE("%s: srl %d, lrl %d\n",
412 conf->short_frame_max_tx_count, 321 __func__,
413 conf->long_frame_max_tx_count)); 322 conf->short_frame_max_tx_count,
323 conf->long_frame_max_tx_count);
414 if (wlc_set 324 if (wlc_set
415 (wl->wlc, WLC_SET_SRL, 325 (wl->wlc, WLC_SET_SRL,
416 conf->short_frame_max_tx_count) < 0) { 326 conf->short_frame_max_tx_count) < 0) {
417 WL_ERROR(("%s: Error setting srl\n", __func__)); 327 WL_ERROR("%s: Error setting srl\n", __func__);
418 err = -EIO; 328 err = -EIO;
419 goto config_out; 329 goto config_out;
420 } 330 }
421 if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count) 331 if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
422 < 0) { 332 < 0) {
423 WL_ERROR(("%s: Error setting lrl\n", __func__)); 333 WL_ERROR("%s: Error setting lrl\n", __func__);
424 err = -EIO; 334 err = -EIO;
425 goto config_out; 335 goto config_out;
426 } 336 }
@@ -435,32 +345,29 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
435 struct ieee80211_vif *vif, 345 struct ieee80211_vif *vif,
436 struct ieee80211_bss_conf *info, u32 changed) 346 struct ieee80211_bss_conf *info, u32 changed)
437{ 347{
438 wl_info_t *wl = HW_TO_WL(hw); 348 struct wl_info *wl = HW_TO_WL(hw);
439 int val; 349 int val;
440 350
441#ifdef WLC_HIGH_ONLY
442 WL_LOCK(wl);
443#endif
444 351
445 if (changed & BSS_CHANGED_ASSOC) { 352 if (changed & BSS_CHANGED_ASSOC) {
446 WL_ERROR(("Associated:\t%s\n", info->assoc ? "True" : "False")); 353 WL_ERROR("Associated:\t%s\n", info->assoc ? "True" : "False");
447 /* association status changed (associated/disassociated) 354 /* association status changed (associated/disassociated)
448 * also implies a change in the AID. 355 * also implies a change in the AID.
449 */ 356 */
450 } 357 }
451 if (changed & BSS_CHANGED_ERP_CTS_PROT) { 358 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
452 WL_NONE(("Use_cts_prot:\t%s Implement me\n", 359 WL_NONE("Use_cts_prot:\t%s Implement me\n",
453 info->use_cts_prot ? "True" : "False")); 360 info->use_cts_prot ? "True" : "False");
454 /* CTS protection changed */ 361 /* CTS protection changed */
455 } 362 }
456 if (changed & BSS_CHANGED_ERP_PREAMBLE) { 363 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
457 WL_NONE(("Short preamble:\t%s Implement me\n", 364 WL_NONE("Short preamble:\t%s Implement me\n",
458 info->use_short_preamble ? "True" : "False")); 365 info->use_short_preamble ? "True" : "False");
459 /* preamble changed */ 366 /* preamble changed */
460 } 367 }
461 if (changed & BSS_CHANGED_ERP_SLOT) { 368 if (changed & BSS_CHANGED_ERP_SLOT) {
462 WL_NONE(("Changing short slot:\t%s\n", 369 WL_NONE("Changing short slot:\t%s\n",
463 info->use_short_slot ? "True" : "False")); 370 info->use_short_slot ? "True" : "False");
464 if (info->use_short_slot) 371 if (info->use_short_slot)
465 val = 1; 372 val = 1;
466 else 373 else
@@ -470,39 +377,36 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
470 } 377 }
471 378
472 if (changed & BSS_CHANGED_HT) { 379 if (changed & BSS_CHANGED_HT) {
473 WL_NONE(("%s: HT mode - Implement me\n", __func__)); 380 WL_NONE("%s: HT mode - Implement me\n", __func__);
474 /* 802.11n parameters changed */ 381 /* 802.11n parameters changed */
475 } 382 }
476 if (changed & BSS_CHANGED_BASIC_RATES) { 383 if (changed & BSS_CHANGED_BASIC_RATES) {
477 WL_NONE(("Need to change Basic Rates:\t0x%x! Implement me\n", 384 WL_NONE("Need to change Basic Rates:\t0x%x! Implement me\n",
478 (u32) info->basic_rates)); 385 (u32) info->basic_rates);
479 /* Basic rateset changed */ 386 /* Basic rateset changed */
480 } 387 }
481 if (changed & BSS_CHANGED_BEACON_INT) { 388 if (changed & BSS_CHANGED_BEACON_INT) {
482 WL_NONE(("Beacon Interval:\t%d Implement me\n", 389 WL_NONE("Beacon Interval:\t%d Implement me\n",
483 info->beacon_int)); 390 info->beacon_int);
484 /* Beacon interval changed */ 391 /* Beacon interval changed */
485 } 392 }
486 if (changed & BSS_CHANGED_BSSID) { 393 if (changed & BSS_CHANGED_BSSID) {
487 WL_NONE(("new BSSID:\taid %d bss:%pM\n", info->aid, 394 WL_NONE("new BSSID:\taid %d bss:%pM\n",
488 info->bssid)); 395 info->aid, info->bssid);
489 /* BSSID changed, for whatever reason (IBSS and managed mode) */ 396 /* BSSID changed, for whatever reason (IBSS and managed mode) */
490 /* FIXME: need to store bssid in bsscfg */ 397 /* FIXME: need to store bssid in bsscfg */
491 wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, 398 wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
492 (struct ether_addr *)info->bssid); 399 (struct ether_addr *)info->bssid);
493 } 400 }
494 if (changed & BSS_CHANGED_BEACON) { 401 if (changed & BSS_CHANGED_BEACON) {
495 WL_ERROR(("BSS_CHANGED_BEACON\n")); 402 WL_ERROR("BSS_CHANGED_BEACON\n");
496 /* Beacon data changed, retrieve new beacon (beaconing modes) */ 403 /* Beacon data changed, retrieve new beacon (beaconing modes) */
497 } 404 }
498 if (changed & BSS_CHANGED_BEACON_ENABLED) { 405 if (changed & BSS_CHANGED_BEACON_ENABLED) {
499 WL_ERROR(("Beacon enabled:\t%s\n", 406 WL_ERROR("Beacon enabled:\t%s\n",
500 info->enable_beacon ? "True" : "False")); 407 info->enable_beacon ? "True" : "False");
501 /* Beaconing should be enabled/disabled (beaconing modes) */ 408 /* Beaconing should be enabled/disabled (beaconing modes) */
502 } 409 }
503#ifdef WLC_HIGH_ONLY
504 WL_UNLOCK(wl);
505#endif
506 return; 410 return;
507} 411}
508 412
@@ -511,27 +415,24 @@ wl_ops_configure_filter(struct ieee80211_hw *hw,
511 unsigned int changed_flags, 415 unsigned int changed_flags,
512 unsigned int *total_flags, u64 multicast) 416 unsigned int *total_flags, u64 multicast)
513{ 417{
514#ifndef WLC_HIGH_ONLY 418 struct wl_info *wl = hw->priv;
515 wl_info_t *wl = hw->priv;
516#endif
517 419
518 changed_flags &= MAC_FILTERS; 420 changed_flags &= MAC_FILTERS;
519 *total_flags &= MAC_FILTERS; 421 *total_flags &= MAC_FILTERS;
520 if (changed_flags & FIF_PROMISC_IN_BSS) 422 if (changed_flags & FIF_PROMISC_IN_BSS)
521 WL_ERROR(("FIF_PROMISC_IN_BSS\n")); 423 WL_ERROR("FIF_PROMISC_IN_BSS\n");
522 if (changed_flags & FIF_ALLMULTI) 424 if (changed_flags & FIF_ALLMULTI)
523 WL_ERROR(("FIF_ALLMULTI\n")); 425 WL_ERROR("FIF_ALLMULTI\n");
524 if (changed_flags & FIF_FCSFAIL) 426 if (changed_flags & FIF_FCSFAIL)
525 WL_ERROR(("FIF_FCSFAIL\n")); 427 WL_ERROR("FIF_FCSFAIL\n");
526 if (changed_flags & FIF_PLCPFAIL) 428 if (changed_flags & FIF_PLCPFAIL)
527 WL_ERROR(("FIF_PLCPFAIL\n")); 429 WL_ERROR("FIF_PLCPFAIL\n");
528 if (changed_flags & FIF_CONTROL) 430 if (changed_flags & FIF_CONTROL)
529 WL_ERROR(("FIF_CONTROL\n")); 431 WL_ERROR("FIF_CONTROL\n");
530 if (changed_flags & FIF_OTHER_BSS) 432 if (changed_flags & FIF_OTHER_BSS)
531 WL_ERROR(("FIF_OTHER_BSS\n")); 433 WL_ERROR("FIF_OTHER_BSS\n");
532 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { 434 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
533 WL_NONE(("FIF_BCN_PRBRESP_PROMISC\n")); 435 WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
534#ifndef WLC_HIGH_ONLY
535 WL_LOCK(wl); 436 WL_LOCK(wl);
536 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { 437 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
537 wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS; 438 wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
@@ -541,7 +442,6 @@ wl_ops_configure_filter(struct ieee80211_hw *hw,
541 wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS; 442 wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
542 } 443 }
543 WL_UNLOCK(wl); 444 WL_UNLOCK(wl);
544#endif
545 } 445 }
546 return; 446 return;
547} 447}
@@ -549,25 +449,25 @@ wl_ops_configure_filter(struct ieee80211_hw *hw,
549static int 449static int
550wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) 450wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
551{ 451{
552 WL_ERROR(("%s: Enter\n", __func__)); 452 WL_ERROR("%s: Enter\n", __func__);
553 return 0; 453 return 0;
554} 454}
555 455
556static void wl_ops_sw_scan_start(struct ieee80211_hw *hw) 456static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
557{ 457{
558 WL_NONE(("Scan Start\n")); 458 WL_NONE("Scan Start\n");
559 return; 459 return;
560} 460}
561 461
562static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw) 462static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
563{ 463{
564 WL_NONE(("Scan Complete\n")); 464 WL_NONE("Scan Complete\n");
565 return; 465 return;
566} 466}
567 467
568static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf) 468static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
569{ 469{
570 WL_ERROR(("%s: Enter\n", __func__)); 470 WL_ERROR("%s: Enter\n", __func__);
571 return; 471 return;
572} 472}
573 473
@@ -575,13 +475,13 @@ static int
575wl_ops_get_stats(struct ieee80211_hw *hw, 475wl_ops_get_stats(struct ieee80211_hw *hw,
576 struct ieee80211_low_level_stats *stats) 476 struct ieee80211_low_level_stats *stats)
577{ 477{
578 WL_ERROR(("%s: Enter\n", __func__)); 478 WL_ERROR("%s: Enter\n", __func__);
579 return 0; 479 return 0;
580} 480}
581 481
582static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 482static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
583{ 483{
584 WL_ERROR(("%s: Enter\n", __func__)); 484 WL_ERROR("%s: Enter\n", __func__);
585 return 0; 485 return 0;
586} 486}
587 487
@@ -589,10 +489,10 @@ static void
589wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 489wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
590 enum sta_notify_cmd cmd, struct ieee80211_sta *sta) 490 enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
591{ 491{
592 WL_NONE(("%s: Enter\n", __func__)); 492 WL_NONE("%s: Enter\n", __func__);
593 switch (cmd) { 493 switch (cmd) {
594 default: 494 default:
595 WL_ERROR(("%s: Uknown cmd = %d\n", __func__, cmd)); 495 WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
596 break; 496 break;
597 } 497 }
598 return; 498 return;
@@ -602,11 +502,11 @@ static int
602wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, 502wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
603 const struct ieee80211_tx_queue_params *params) 503 const struct ieee80211_tx_queue_params *params)
604{ 504{
605 wl_info_t *wl = hw->priv; 505 struct wl_info *wl = hw->priv;
606 506
607 WL_NONE(("%s: Enter (WME config)\n", __func__)); 507 WL_NONE("%s: Enter (WME config)\n", __func__);
608 WL_NONE(("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue, 508 WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
609 params->txop, params->cw_min, params->cw_max, params->aifs)); 509 params->txop, params->cw_min, params->cw_max, params->aifs);
610 510
611 WL_LOCK(wl); 511 WL_LOCK(wl);
612 wlc_wme_setparams(wl->wlc, queue, (void *)params, true); 512 wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
@@ -617,7 +517,7 @@ wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
617 517
618static u64 wl_ops_get_tsf(struct ieee80211_hw *hw) 518static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
619{ 519{
620 WL_ERROR(("%s: Enter\n", __func__)); 520 WL_ERROR("%s: Enter\n", __func__);
621 return 0; 521 return 0;
622} 522}
623 523
@@ -628,11 +528,11 @@ wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
628 struct scb *scb; 528 struct scb *scb;
629 529
630 int i; 530 int i;
631 wl_info_t *wl = hw->priv; 531 struct wl_info *wl = hw->priv;
632 532
633 /* Init the scb */ 533 /* Init the scb */
634 scb = (struct scb *)sta->drv_priv; 534 scb = (struct scb *)sta->drv_priv;
635 bzero(scb, sizeof(struct scb)); 535 memset(scb, 0, sizeof(struct scb));
636 for (i = 0; i < NUMPRIO; i++) 536 for (i = 0; i < NUMPRIO; i++)
637 scb->seqctl[i] = 0xFFFF; 537 scb->seqctl[i] = 0xFFFF;
638 scb->seqctl_nonqos = 0xFFFF; 538 scb->seqctl_nonqos = 0xFFFF;
@@ -641,20 +541,12 @@ wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
641 wl->pub->global_scb = scb; 541 wl->pub->global_scb = scb;
642 wl->pub->global_ampdu = &(scb->scb_ampdu); 542 wl->pub->global_ampdu = &(scb->scb_ampdu);
643 wl->pub->global_ampdu->scb = scb; 543 wl->pub->global_ampdu->scb = scb;
644#ifdef WLC_HIGH_ONLY
645 wl->pub->global_ampdu->max_pdu = AMPDU_NUM_MPDU;
646#else
647 wl->pub->global_ampdu->max_pdu = 16; 544 wl->pub->global_ampdu->max_pdu = 16;
648#endif
649 pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID, 545 pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
650 AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT); 546 AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
651 547
652 sta->ht_cap.ht_supported = true; 548 sta->ht_cap.ht_supported = true;
653#ifdef WLC_HIGH_ONLY
654 sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_16K;
655#else
656 sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_64K; 549 sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_64K;
657#endif
658 sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY; 550 sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
659 sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD | 551 sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
660 IEEE80211_HT_CAP_SGI_20 | 552 IEEE80211_HT_CAP_SGI_20 |
@@ -668,7 +560,7 @@ static int
668wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 560wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
669 struct ieee80211_sta *sta) 561 struct ieee80211_sta *sta)
670{ 562{
671 WL_NONE(("%s: Enter\n", __func__)); 563 WL_NONE("%s: Enter\n", __func__);
672 return 0; 564 return 0;
673} 565}
674 566
@@ -681,19 +573,19 @@ wl_ampdu_action(struct ieee80211_hw *hw,
681#if defined(BCMDBG) 573#if defined(BCMDBG)
682 struct scb *scb = (struct scb *)sta->drv_priv; 574 struct scb *scb = (struct scb *)sta->drv_priv;
683#endif 575#endif
684 wl_info_t *wl = hw->priv; 576 struct wl_info *wl = hw->priv;
685 577
686 ASSERT(scb->magic == SCB_MAGIC); 578 ASSERT(scb->magic == SCB_MAGIC);
687 switch (action) { 579 switch (action) {
688 case IEEE80211_AMPDU_RX_START: 580 case IEEE80211_AMPDU_RX_START:
689 WL_NONE(("%s: action = IEEE80211_AMPDU_RX_START\n", __func__)); 581 WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
690 break; 582 break;
691 case IEEE80211_AMPDU_RX_STOP: 583 case IEEE80211_AMPDU_RX_STOP:
692 WL_NONE(("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__)); 584 WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
693 break; 585 break;
694 case IEEE80211_AMPDU_TX_START: 586 case IEEE80211_AMPDU_TX_START:
695 if (!wlc_aggregatable(wl->wlc, tid)) { 587 if (!wlc_aggregatable(wl->wlc, tid)) {
696 /* WL_ERROR(("START: tid %d is not agg' able, return FAILURE to stack\n", tid)); */ 588 /* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
697 return -1; 589 return -1;
698 } 590 }
699 /* XXX: Use the starting sequence number provided ... */ 591 /* XXX: Use the starting sequence number provided ... */
@@ -707,22 +599,18 @@ wl_ampdu_action(struct ieee80211_hw *hw,
707 case IEEE80211_AMPDU_TX_OPERATIONAL: 599 case IEEE80211_AMPDU_TX_OPERATIONAL:
708 /* Not sure what to do here */ 600 /* Not sure what to do here */
709 /* Power save wakeup */ 601 /* Power save wakeup */
710 WL_NONE(("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n", 602 WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
711 __func__)); 603 __func__);
712 break; 604 break;
713 default: 605 default:
714 WL_ERROR(("%s: Invalid command, ignoring\n", __func__)); 606 WL_ERROR("%s: Invalid command, ignoring\n", __func__);
715 } 607 }
716 608
717 return 0; 609 return 0;
718} 610}
719 611
720static const struct ieee80211_ops wl_ops = { 612static const struct ieee80211_ops wl_ops = {
721#ifdef WLC_HIGH_ONLY
722 .tx = wl_ops_tx_nl,
723#else
724 .tx = wl_ops_tx, 613 .tx = wl_ops_tx,
725#endif
726 .start = wl_ops_start, 614 .start = wl_ops_start,
727 .stop = wl_ops_stop, 615 .stop = wl_ops_stop,
728 .add_interface = wl_ops_add_interface, 616 .add_interface = wl_ops_add_interface,
@@ -744,10 +632,10 @@ static const struct ieee80211_ops wl_ops = {
744 .ampdu_action = wl_ampdu_action, 632 .ampdu_action = wl_ampdu_action,
745}; 633};
746 634
747static int wl_set_hint(wl_info_t *wl, char *abbrev) 635static int wl_set_hint(struct wl_info *wl, char *abbrev)
748{ 636{
749 WL_ERROR(("%s: Sending country code %c%c to MAC80211\n", __func__, 637 WL_ERROR("%s: Sending country code %c%c to MAC80211\n",
750 abbrev[0], abbrev[1])); 638 __func__, abbrev[0], abbrev[1]);
751 return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); 639 return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
752} 640}
753 641
@@ -762,117 +650,61 @@ static int wl_set_hint(wl_info_t *wl, char *abbrev)
762 * a warning that this function is defined but not used if we declare 650 * a warning that this function is defined but not used if we declare
763 * it as static. 651 * it as static.
764 */ 652 */
765static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs, 653static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
766 uint bustype, void *btparam, uint irq) 654 uint bustype, void *btparam, uint irq)
767{ 655{
768 wl_info_t *wl; 656 struct wl_info *wl;
769 osl_t *osh; 657 struct osl_info *osh;
770 int unit, err; 658 int unit, err;
771 659
772 unsigned long base_addr; 660 unsigned long base_addr;
773 struct ieee80211_hw *hw; 661 struct ieee80211_hw *hw;
774 u8 perm[ETH_ALEN]; 662 u8 perm[ETH_ALEN];
775 663
776 unit = wl_found + instance_base; 664 unit = wl_found;
777 err = 0; 665 err = 0;
778 666
779 if (unit < 0) { 667 if (unit < 0) {
780 WL_ERROR(("wl%d: unit number overflow, exiting\n", unit)); 668 WL_ERROR("wl%d: unit number overflow, exiting\n", unit);
781 return NULL; 669 return NULL;
782 } 670 }
783 671
784 if (oneonly && (unit != instance_base)) { 672 osh = osl_attach(btparam, bustype);
785 WL_ERROR(("wl%d: wl_attach: oneonly is set, exiting\n", unit));
786 return NULL;
787 }
788
789 /* Requires pkttag feature */
790 osh = osl_attach(btparam, bustype, true);
791 ASSERT(osh); 673 ASSERT(osh);
792 674
793#ifdef WLC_HIGH_ONLY
794 hw = ieee80211_alloc_hw(sizeof(wl_info_t), &wl_ops);
795 if (!hw) {
796 WL_ERROR(("%s: ieee80211_alloc_hw failed\n", __func__));
797 ASSERT(0);
798 }
799
800 bzero(hw->priv, sizeof(*wl));
801 wl = hw->priv;
802#else
803 /* allocate private info */ 675 /* allocate private info */
804 hw = pci_get_drvdata(btparam); /* btparam == pdev */ 676 hw = pci_get_drvdata(btparam); /* btparam == pdev */
805 wl = hw->priv; 677 wl = hw->priv;
806#endif
807 ASSERT(wl); 678 ASSERT(wl);
808 679
809 wl->magic = WL_MAGIC;
810 wl->osh = osh; 680 wl->osh = osh;
811 atomic_set(&wl->callbacks, 0); 681 atomic_set(&wl->callbacks, 0);
812 682
813 /* setup the bottom half handler */ 683 /* setup the bottom half handler */
814 tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl); 684 tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
815 685
816#ifdef WLC_HIGH_ONLY
817 wl->rpc_th = bcm_rpc_tp_attach(osh, NULL);
818 if (wl->rpc_th == NULL) {
819 WL_ERROR(("wl%d: %s: bcm_rpc_tp_attach failed!\n", unit,
820 __func__));
821 goto fail;
822 }
823
824 wl->rpc = bcm_rpc_attach(NULL, osh, wl->rpc_th);
825 if (wl->rpc == NULL) {
826 WL_ERROR(("wl%d: %s: bcm_rpc_attach failed!\n", unit,
827 __func__));
828 goto fail;
829 }
830
831 /* init tx work queue for wl_start/send pkt; no need to destroy workitem */
832 INIT_WORK(&wl->txq_task.work, (work_func_t) wl_start_txqwork);
833 wl->txq_task.context = wl;
834#endif /* WLC_HIGH_ONLY */
835 686
836#ifdef BCMSDIO
837 SET_IEEE80211_DEV(hw, sdiommc_dev);
838#endif
839 687
840 base_addr = regs; 688 base_addr = regs;
841 689
842 if (bustype == PCI_BUS) { 690 if (bustype == PCI_BUS) {
843 /* piomode can be overwritten by command argument */ 691 wl->piomode = false;
844 wl->piomode = piomode;
845 WL_TRACE(("PCI/%s\n", wl->piomode ? "PIO" : "DMA"));
846 } else if (bustype == RPC_BUS) { 692 } else if (bustype == RPC_BUS) {
847 /* Do nothing */ 693 /* Do nothing */
848 } else { 694 } else {
849 bustype = PCI_BUS; 695 bustype = PCI_BUS;
850 WL_TRACE(("force to PCI\n")); 696 WL_TRACE("force to PCI\n");
851 } 697 }
852 wl->bcm_bustype = bustype; 698 wl->bcm_bustype = bustype;
853 699
854#ifdef WLC_HIGH_ONLY
855 if (wl->bcm_bustype == RPC_BUS) {
856 wl->regsva = (void *)0;
857 btparam = wl->rpc;
858 } else
859#endif
860 wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ); 700 wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
861 if (wl->regsva == NULL) { 701 if (wl->regsva == NULL) {
862 WL_ERROR(("wl%d: ioremap() failed\n", unit)); 702 WL_ERROR("wl%d: ioremap() failed\n", unit);
863 goto fail; 703 goto fail;
864 } 704 }
865#ifdef WLC_HIGH_ONLY
866 spin_lock_init(&wl->rpcq_lock);
867 spin_lock_init(&wl->txq_lock);
868
869 sema_init(&wl->sem, 1);
870#else
871 spin_lock_init(&wl->lock); 705 spin_lock_init(&wl->lock);
872 spin_lock_init(&wl->isr_lock); 706 spin_lock_init(&wl->isr_lock);
873#endif
874 707
875#ifndef WLC_HIGH_ONLY
876 /* prepare ucode */ 708 /* prepare ucode */
877 if (wl_request_fw(wl, (struct pci_dev *)btparam)) { 709 if (wl_request_fw(wl, (struct pci_dev *)btparam)) {
878 printf("%s: Failed to find firmware usually in %s\n", 710 printf("%s: Failed to find firmware usually in %s\n",
@@ -881,17 +713,14 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs,
881 wl_remove((struct pci_dev *)btparam); 713 wl_remove((struct pci_dev *)btparam);
882 goto fail1; 714 goto fail1;
883 } 715 }
884#endif
885 716
886 /* common load-time initialization */ 717 /* common load-time initialization */
887 wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh, 718 wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh,
888 wl->regsva, wl->bcm_bustype, btparam, &err); 719 wl->regsva, wl->bcm_bustype, btparam, &err);
889#ifndef WLC_HIGH_ONLY
890 wl_release_fw(wl); 720 wl_release_fw(wl);
891#endif
892 if (!wl->wlc) { 721 if (!wl->wlc) {
893 printf("%s: %s wlc_attach() failed with code %d\n", 722 printf("%s: wlc_attach() failed with code %d\n",
894 KBUILD_MODNAME, EPI_VERSION_STR, err); 723 KBUILD_MODNAME, err);
895 goto fail; 724 goto fail;
896 } 725 }
897 wl->pub = wlc_pub(wl->wlc); 726 wl->pub = wlc_pub(wl->wlc);
@@ -900,52 +729,35 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs,
900 ASSERT(wl->pub->ieee_hw); 729 ASSERT(wl->pub->ieee_hw);
901 ASSERT(wl->pub->ieee_hw->priv == wl); 730 ASSERT(wl->pub->ieee_hw->priv == wl);
902 731
903#ifdef WLC_HIGH_ONLY 732
904 REGOPSSET(osh, (osl_rreg_fn_t) wlc_reg_read, 733 if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
905 (osl_wreg_fn_t) wlc_reg_write, wl->wlc); 734 WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit);
906 wl->rpc_dispatch_ctx.rpc = wl->rpc;
907 wl->rpc_dispatch_ctx.wlc = wl->wlc;
908 bcm_rpc_rxcb_init(wl->rpc, wl, wl_rpc_dispatch_schedule, wl,
909 wl_rpc_down, NULL, NULL);
910#endif /* WLC_HIGH_ONLY */
911
912 if (nompc) {
913 if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
914 WL_ERROR(("wl%d: Error setting MPC variable to 0\n",
915 unit));
916 }
917 } 735 }
918#ifdef BCMSDIO
919 /* Set SDIO drive strength */
920 wlc_iovar_setint(wl->wlc, "sd_drivestrength", sd_drivestrength);
921#endif
922 736
923#ifdef WLC_LOW
924 /* register our interrupt handler */ 737 /* register our interrupt handler */
925 if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { 738 if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
926 WL_ERROR(("wl%d: request_irq() failed\n", unit)); 739 WL_ERROR("wl%d: request_irq() failed\n", unit);
927 goto fail; 740 goto fail;
928 } 741 }
929 wl->irq = irq; 742 wl->irq = irq;
930#endif /* WLC_LOW */
931 743
932 /* register module */ 744 /* register module */
933 wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, 745 wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
934 NULL); 746 NULL);
935 747
936 if (ieee_hw_init(hw)) { 748 if (ieee_hw_init(hw)) {
937 WL_ERROR(("wl%d: %s: ieee_hw_init failed!\n", unit, __func__)); 749 WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit, __func__);
938 goto fail; 750 goto fail;
939 } 751 }
940 752
941 bcopy(&wl->pub->cur_etheraddr, perm, ETHER_ADDR_LEN); 753 bcopy(&wl->pub->cur_etheraddr, perm, ETH_ALEN);
942 ASSERT(is_valid_ether_addr(perm)); 754 ASSERT(is_valid_ether_addr(perm));
943 SET_IEEE80211_PERM_ADDR(hw, perm); 755 SET_IEEE80211_PERM_ADDR(hw, perm);
944 756
945 err = ieee80211_register_hw(hw); 757 err = ieee80211_register_hw(hw);
946 if (err) { 758 if (err) {
947 WL_ERROR(("%s: ieee80211_register_hw failed, status %d\n", 759 WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
948 __func__, err)); 760 __func__, err);
949 } 761 }
950 762
951 if (wl->pub->srom_ccode[0]) 763 if (wl->pub->srom_ccode[0])
@@ -953,19 +765,14 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs,
953 else 765 else
954 err = wl_set_hint(wl, "US"); 766 err = wl_set_hint(wl, "US");
955 if (err) { 767 if (err) {
956 WL_ERROR(("%s: regulatory_hint failed, status %d\n", __func__, 768 WL_ERROR("%s: regulatory_hint failed, status %d\n",
957 err)); 769 __func__, err);
958 } 770 }
959#ifndef WLC_HIGH_ONLY 771 WL_ERROR("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver (" PHY_VERSION_STR ")",
960 WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver " 772 unit);
961 EPI_VERSION_STR " (" PHY_VERSION_STR ")", unit));
962#else
963 WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver "
964 EPI_VERSION_STR, unit));
965#endif
966 773
967#ifdef BCMDBG 774#ifdef BCMDBG
968 printf(" (Compiled in " SRCBASE " at " __TIME__ " on " __DATE__ ")"); 775 printf(" (Compiled at " __TIME__ " on " __DATE__ ")");
969#endif /* BCMDBG */ 776#endif /* BCMDBG */
970 printf("\n"); 777 printf("\n");
971 778
@@ -978,54 +785,6 @@ fail1:
978 return NULL; 785 return NULL;
979} 786}
980 787
981#ifdef WLC_HIGH_ONLY
982static void *wl_dbus_probe_cb(void *arg, const char *desc, u32 bustype,
983 u32 hdrlen)
984{
985 wl_info_t *wl;
986 WL_ERROR(("%s:\n", __func__));
987
988 wl = wl_attach(BCM_DNGL_VID, BCM_DNGL_BDC_PID, (unsigned long) NULL, RPC_BUS,
989 NULL, 0);
990 if (!wl) {
991 WL_ERROR(("%s: wl_attach failed\n", __func__));
992 }
993
994 /* This is later passed to wl_dbus_disconnect_cb */
995 return wl;
996}
997
998static void wl_dbus_disconnect_cb(void *arg)
999{
1000 wl_info_t *wl = arg;
1001
1002 WL_ERROR(("%s:\n", __func__));
1003
1004 if (wl) {
1005#ifdef WLC_HIGH_ONLY
1006 if (wl->pub->ieee_hw) {
1007 ieee80211_unregister_hw(wl->pub->ieee_hw);
1008 WL_ERROR(("%s: Back from down\n", __func__));
1009 }
1010 wlc_device_removed(wl->wlc);
1011 wlc_bmac_dngl_reboot(wl->rpc);
1012 bcm_rpc_down(wl->rpc);
1013#endif
1014 WL_LOCK(wl);
1015 wl_down(wl);
1016 WL_UNLOCK(wl);
1017#ifdef WLC_HIGH_ONLY
1018 if (wl->pub->ieee_hw) {
1019 ieee80211_free_hw(wl->pub->ieee_hw);
1020 WL_ERROR(("%s: Back from ieee80211_free_hw\n",
1021 __func__));
1022 wl->pub->ieee_hw = NULL;
1023 }
1024#endif
1025 wl_free(wl);
1026 }
1027}
1028#endif /* WLC_HIGH_ONLY */
1029 788
1030 789
1031#define CHAN2GHZ(channel, freqency, chflags) { \ 790#define CHAN2GHZ(channel, freqency, chflags) { \
@@ -1163,29 +922,13 @@ static struct ieee80211_supported_band wl_band_2GHz_nphy = {
1163 .cap = IEEE80211_HT_CAP_GRN_FLD | 922 .cap = IEEE80211_HT_CAP_GRN_FLD |
1164 IEEE80211_HT_CAP_SGI_20 | 923 IEEE80211_HT_CAP_SGI_20 |
1165 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, 924 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
1166#ifdef WLC_HIGH_ONLY
1167 .ht_supported = true,
1168 .ampdu_factor = AMPDU_RX_FACTOR_16K,
1169#else
1170 .ht_supported = true, 925 .ht_supported = true,
1171 .ampdu_factor = AMPDU_RX_FACTOR_64K, 926 .ampdu_factor = AMPDU_RX_FACTOR_64K,
1172#endif
1173 .ampdu_density = AMPDU_DEF_MPDU_DENSITY, 927 .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
1174 .mcs = { 928 .mcs = {
1175 /* placeholders for now */ 929 /* placeholders for now */
1176#ifdef WLC_HIGH_ONLY
1177 /*
1178 * rx_mask[0] = 0xff by default
1179 * rx_mask[1] = 0xff if number of rx chain >=2
1180 * rx_mask[2] = 0xff if number of rx chain >=3
1181 * rx_mask[4] = 1 if 40Mhz is supported
1182 */
1183 .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1184 .rx_highest = 72, /* max rate of single stream */
1185#else
1186 .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, 930 .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
1187 .rx_highest = 500, 931 .rx_highest = 500,
1188#endif
1189 .tx_params = IEEE80211_HT_MCS_TX_DEFINED} 932 .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
1190 } 933 }
1191}; 934};
@@ -1212,7 +955,7 @@ static struct ieee80211_supported_band wl_band_5GHz_nphy = {
1212 955
1213static int ieee_hw_rate_init(struct ieee80211_hw *hw) 956static int ieee_hw_rate_init(struct ieee80211_hw *hw)
1214{ 957{
1215 wl_info_t *wl = HW_TO_WL(hw); 958 struct wl_info *wl = HW_TO_WL(hw);
1216 int has_5g; 959 int has_5g;
1217 char phy_list[4]; 960 char phy_list[4];
1218 961
@@ -1222,20 +965,16 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
1222 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; 965 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
1223 966
1224 if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) { 967 if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
1225 WL_ERROR(("Phy list failed\n")); 968 WL_ERROR("Phy list failed\n");
1226 } 969 }
1227 WL_NONE(("%s: phylist = %c\n", __func__, phy_list[0])); 970 WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);
1228 971
1229#ifndef WLC_HIGH_ONLY
1230 if (phy_list[0] == 'n' || phy_list[0] == 'c') { 972 if (phy_list[0] == 'n' || phy_list[0] == 'c') {
1231 if (phy_list[0] == 'c') { 973 if (phy_list[0] == 'c') {
1232 /* Single stream */ 974 /* Single stream */
1233 wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0; 975 wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
1234 wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72; 976 wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
1235 } 977 }
1236#else
1237 if (phy_list[0] == 's') {
1238#endif
1239 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy; 978 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
1240 } else { 979 } else {
1241 BUG(); 980 BUG();
@@ -1245,11 +984,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
1245 /* Assume all bands use the same phy. True for 11n devices. */ 984 /* Assume all bands use the same phy. True for 11n devices. */
1246 if (NBANDS_PUB(wl->pub) > 1) { 985 if (NBANDS_PUB(wl->pub) > 1) {
1247 has_5g++; 986 has_5g++;
1248#ifndef WLC_HIGH_ONLY
1249 if (phy_list[0] == 'n' || phy_list[0] == 'c') { 987 if (phy_list[0] == 'n' || phy_list[0] == 'c') {
1250#else
1251 if (phy_list[0] == 's') {
1252#endif
1253 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 988 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1254 &wl_band_5GHz_nphy; 989 &wl_band_5GHz_nphy;
1255 } else { 990 } else {
@@ -1257,7 +992,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
1257 } 992 }
1258 } 993 }
1259 994
1260 WL_NONE(("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g)); 995 WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);
1261 996
1262 return 0; 997 return 0;
1263} 998}
@@ -1288,7 +1023,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
1288 return ieee_hw_rate_init(hw); 1023 return ieee_hw_rate_init(hw);
1289} 1024}
1290 1025
1291#ifndef BCMSDIO
1292/** 1026/**
1293 * determines if a device is a WL device, and if so, attaches it. 1027 * determines if a device is a WL device, and if so, attaches it.
1294 * 1028 *
@@ -1300,15 +1034,15 @@ int __devinit
1300wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1034wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1301{ 1035{
1302 int rc; 1036 int rc;
1303 wl_info_t *wl; 1037 struct wl_info *wl;
1304 struct ieee80211_hw *hw; 1038 struct ieee80211_hw *hw;
1305 u32 val; 1039 u32 val;
1306 1040
1307 ASSERT(pdev); 1041 ASSERT(pdev);
1308 1042
1309 WL_TRACE(("%s: bus %d slot %d func %d irq %d\n", __func__, 1043 WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
1310 pdev->bus->number, PCI_SLOT(pdev->devfn), 1044 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
1311 PCI_FUNC(pdev->devfn), pdev->irq)); 1045 PCI_FUNC(pdev->devfn), pdev->irq);
1312 1046
1313 if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || 1047 if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
1314 (((pdev->device & 0xff00) != 0x4300) && 1048 (((pdev->device & 0xff00) != 0x4300) &&
@@ -1318,9 +1052,9 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1318 1052
1319 rc = pci_enable_device(pdev); 1053 rc = pci_enable_device(pdev);
1320 if (rc) { 1054 if (rc) {
1321 WL_ERROR(("%s: Cannot enable device %d-%d_%d\n", __func__, 1055 WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
1322 pdev->bus->number, PCI_SLOT(pdev->devfn), 1056 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
1323 PCI_FUNC(pdev->devfn))); 1057 PCI_FUNC(pdev->devfn));
1324 return -ENODEV; 1058 return -ENODEV;
1325 } 1059 }
1326 pci_set_master(pdev); 1060 pci_set_master(pdev);
@@ -1329,9 +1063,9 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1329 if ((val & 0x0000ff00) != 0) 1063 if ((val & 0x0000ff00) != 0)
1330 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); 1064 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
1331 1065
1332 hw = ieee80211_alloc_hw(sizeof(wl_info_t), &wl_ops); 1066 hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
1333 if (!hw) { 1067 if (!hw) {
1334 WL_ERROR(("%s: ieee80211_alloc_hw failed\n", __func__)); 1068 WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__);
1335 rc = -ENOMEM; 1069 rc = -ENOMEM;
1336 goto err_1; 1070 goto err_1;
1337 } 1071 }
@@ -1340,34 +1074,34 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1340 1074
1341 pci_set_drvdata(pdev, hw); 1075 pci_set_drvdata(pdev, hw);
1342 1076
1343 bzero(hw->priv, sizeof(*wl)); 1077 memset(hw->priv, 0, sizeof(*wl));
1344 1078
1345 wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0), 1079 wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
1346 PCI_BUS, pdev, pdev->irq); 1080 PCI_BUS, pdev, pdev->irq);
1347 1081
1348 if (!wl) { 1082 if (!wl) {
1349 WL_ERROR(("%s: %s: wl_attach failed!\n", 1083 WL_ERROR("%s: %s: wl_attach failed!\n",
1350 KBUILD_MODNAME, __func__)); 1084 KBUILD_MODNAME, __func__);
1351 return -ENODEV; 1085 return -ENODEV;
1352 } 1086 }
1353 return 0; 1087 return 0;
1354 err_1: 1088 err_1:
1355 WL_ERROR(("%s: err_1: Major hoarkage\n", __func__)); 1089 WL_ERROR("%s: err_1: Major hoarkage\n", __func__);
1356 return 0; 1090 return 0;
1357} 1091}
1358 1092
1359#ifdef LINUXSTA_PS 1093#ifdef LINUXSTA_PS
1360static int wl_suspend(struct pci_dev *pdev, pm_message_t state) 1094static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
1361{ 1095{
1362 wl_info_t *wl; 1096 struct wl_info *wl;
1363 struct ieee80211_hw *hw; 1097 struct ieee80211_hw *hw;
1364 1098
1365 WL_TRACE(("wl: wl_suspend\n")); 1099 WL_TRACE("wl: wl_suspend\n");
1366 1100
1367 hw = pci_get_drvdata(pdev); 1101 hw = pci_get_drvdata(pdev);
1368 wl = HW_TO_WL(hw); 1102 wl = HW_TO_WL(hw);
1369 if (!wl) { 1103 if (!wl) {
1370 WL_ERROR(("wl: wl_suspend: pci_get_drvdata failed\n")); 1104 WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
1371 return -ENODEV; 1105 return -ENODEV;
1372 } 1106 }
1373 1107
@@ -1382,16 +1116,16 @@ static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
1382 1116
1383static int wl_resume(struct pci_dev *pdev) 1117static int wl_resume(struct pci_dev *pdev)
1384{ 1118{
1385 wl_info_t *wl; 1119 struct wl_info *wl;
1386 struct ieee80211_hw *hw; 1120 struct ieee80211_hw *hw;
1387 int err = 0; 1121 int err = 0;
1388 u32 val; 1122 u32 val;
1389 1123
1390 WL_TRACE(("wl: wl_resume\n")); 1124 WL_TRACE("wl: wl_resume\n");
1391 hw = pci_get_drvdata(pdev); 1125 hw = pci_get_drvdata(pdev);
1392 wl = HW_TO_WL(hw); 1126 wl = HW_TO_WL(hw);
1393 if (!wl) { 1127 if (!wl) {
1394 WL_ERROR(("wl: wl_resume: pci_get_drvdata failed\n")); 1128 WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
1395 return -ENODEV; 1129 return -ENODEV;
1396 } 1130 }
1397 1131
@@ -1421,17 +1155,17 @@ static int wl_resume(struct pci_dev *pdev)
1421 1155
1422static void wl_remove(struct pci_dev *pdev) 1156static void wl_remove(struct pci_dev *pdev)
1423{ 1157{
1424 wl_info_t *wl; 1158 struct wl_info *wl;
1425 struct ieee80211_hw *hw; 1159 struct ieee80211_hw *hw;
1426 1160
1427 hw = pci_get_drvdata(pdev); 1161 hw = pci_get_drvdata(pdev);
1428 wl = HW_TO_WL(hw); 1162 wl = HW_TO_WL(hw);
1429 if (!wl) { 1163 if (!wl) {
1430 WL_ERROR(("wl: wl_remove: pci_get_drvdata failed\n")); 1164 WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
1431 return; 1165 return;
1432 } 1166 }
1433 if (!wlc_chipmatch(pdev->vendor, pdev->device)) { 1167 if (!wlc_chipmatch(pdev->vendor, pdev->device)) {
1434 WL_ERROR(("wl: wl_remove: wlc_chipmatch failed\n")); 1168 WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
1435 return; 1169 return;
1436 } 1170 }
1437 if (wl->wlc) { 1171 if (wl->wlc) {
@@ -1439,7 +1173,7 @@ static void wl_remove(struct pci_dev *pdev)
1439 WL_LOCK(wl); 1173 WL_LOCK(wl);
1440 wl_down(wl); 1174 wl_down(wl);
1441 WL_UNLOCK(wl); 1175 WL_UNLOCK(wl);
1442 WL_NONE(("%s: Down\n", __func__)); 1176 WL_NONE("%s: Down\n", __func__);
1443 } 1177 }
1444 pci_disable_device(pdev); 1178 pci_disable_device(pdev);
1445 1179
@@ -1459,7 +1193,6 @@ static struct pci_driver wl_pci_driver = {
1459 .remove = __devexit_p(wl_remove), 1193 .remove = __devexit_p(wl_remove),
1460 .id_table = wl_id_table, 1194 .id_table = wl_id_table,
1461}; 1195};
1462#endif /* !BCMSDIO */
1463 1196
1464/** 1197/**
1465 * This is the main entry point for the WL driver. 1198 * This is the main entry point for the WL driver.
@@ -1480,7 +1213,6 @@ static int __init wl_module_init(void)
1480 if (var) 1213 if (var)
1481 wl_msg_level = simple_strtoul(var, NULL, 0); 1214 wl_msg_level = simple_strtoul(var, NULL, 0);
1482 } 1215 }
1483#ifndef WLC_HIGH_ONLY
1484 { 1216 {
1485 extern u32 phyhal_msg_level; 1217 extern u32 phyhal_msg_level;
1486 1218
@@ -1492,25 +1224,13 @@ static int __init wl_module_init(void)
1492 phyhal_msg_level = simple_strtoul(var, NULL, 0); 1224 phyhal_msg_level = simple_strtoul(var, NULL, 0);
1493 } 1225 }
1494 } 1226 }
1495#endif /* WLC_HIGH_ONLY */
1496#endif /* BCMDBG */ 1227#endif /* BCMDBG */
1497 1228
1498#ifndef BCMSDIO
1499 error = pci_register_driver(&wl_pci_driver); 1229 error = pci_register_driver(&wl_pci_driver);
1500 if (!error) 1230 if (!error)
1501 return 0; 1231 return 0;
1502 1232
1503#endif /* !BCMSDIO */
1504 1233
1505#ifdef WLC_HIGH_ONLY
1506 /* BMAC_NOTE: define hardcode number, why NODEVICE is ok ? */
1507 error =
1508 dbus_register(BCM_DNGL_VID, 0, wl_dbus_probe_cb,
1509 wl_dbus_disconnect_cb, NULL, NULL, NULL);
1510 if (error == DBUS_ERR_NODEVICE) {
1511 error = DBUS_OK;
1512 }
1513#endif /* WLC_HIGH_ONLY */
1514 1234
1515 return error; 1235 return error;
1516} 1236}
@@ -1524,13 +1244,8 @@ static int __init wl_module_init(void)
1524 */ 1244 */
1525static void __exit wl_module_exit(void) 1245static void __exit wl_module_exit(void)
1526{ 1246{
1527#ifndef BCMSDIO
1528 pci_unregister_driver(&wl_pci_driver); 1247 pci_unregister_driver(&wl_pci_driver);
1529#endif /* !BCMSDIO */
1530 1248
1531#ifdef WLC_HIGH_ONLY
1532 dbus_deregister();
1533#endif /* WLC_HIGH_ONLY */
1534} 1249}
1535 1250
1536module_init(wl_module_init); 1251module_init(wl_module_init);
@@ -1543,19 +1258,17 @@ module_exit(wl_module_exit);
1543 * by the wl parameter. 1258 * by the wl parameter.
1544 * 1259 *
1545 */ 1260 */
1546void wl_free(wl_info_t *wl) 1261void wl_free(struct wl_info *wl)
1547{ 1262{
1548 wl_timer_t *t, *next; 1263 wl_timer_t *t, *next;
1549 osl_t *osh; 1264 struct osl_info *osh;
1550 1265
1551 ASSERT(wl); 1266 ASSERT(wl);
1552#ifndef WLC_HIGH_ONLY
1553 /* free ucode data */ 1267 /* free ucode data */
1554 if (wl->fw.fw_cnt) 1268 if (wl->fw.fw_cnt)
1555 wl_ucode_data_free(); 1269 wl_ucode_data_free();
1556 if (wl->irq) 1270 if (wl->irq)
1557 free_irq(wl->irq, wl); 1271 free_irq(wl->irq, wl);
1558#endif
1559 1272
1560 /* kill dpc */ 1273 /* kill dpc */
1561 tasklet_kill(&wl->tasklet); 1274 tasklet_kill(&wl->tasklet);
@@ -1593,103 +1306,50 @@ void wl_free(wl_info_t *wl)
1593 * unregister_netdev() calls get_stats() which may read chip registers 1306 * unregister_netdev() calls get_stats() which may read chip registers
1594 * so we cannot unmap the chip registers until after calling unregister_netdev() . 1307 * so we cannot unmap the chip registers until after calling unregister_netdev() .
1595 */ 1308 */
1596 if (wl->regsva && BUSTYPE(wl->bcm_bustype) != SDIO_BUS && 1309 if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
1597 BUSTYPE(wl->bcm_bustype) != JTAG_BUS) { 1310 wl->bcm_bustype != JTAG_BUS) {
1598 iounmap((void *)wl->regsva); 1311 iounmap((void *)wl->regsva);
1599 } 1312 }
1600 wl->regsva = NULL; 1313 wl->regsva = NULL;
1601 1314
1602#ifdef WLC_HIGH_ONLY
1603 wl_rpcq_free(wl);
1604
1605 wl_txq_free(wl);
1606
1607 if (wl->rpc) {
1608 bcm_rpc_detach(wl->rpc);
1609 wl->rpc = NULL;
1610 }
1611
1612 if (wl->rpc_th) {
1613 bcm_rpc_tp_detach(wl->rpc_th);
1614 wl->rpc_th = NULL;
1615 }
1616#endif /* WLC_HIGH_ONLY */
1617 1315
1618 osl_detach(osh); 1316 osl_detach(osh);
1619} 1317}
1620 1318
1621#ifdef WLC_LOW
1622/* transmit a packet */ 1319/* transmit a packet */
1623static int BCMFASTPATH wl_start(struct sk_buff *skb, wl_info_t *wl) 1320static int BCMFASTPATH wl_start(struct sk_buff *skb, struct wl_info *wl)
1624{ 1321{
1625 if (!wl) 1322 if (!wl)
1626 return -ENETDOWN; 1323 return -ENETDOWN;
1627 1324
1628 return wl_start_int(wl, WL_TO_HW(wl), skb); 1325 return wl_start_int(wl, WL_TO_HW(wl), skb);
1629} 1326}
1630#endif /* WLC_LOW */
1631 1327
1632static int BCMFASTPATH 1328static int BCMFASTPATH
1633wl_start_int(wl_info_t *wl, struct ieee80211_hw *hw, struct sk_buff *skb) 1329wl_start_int(struct wl_info *wl, struct ieee80211_hw *hw, struct sk_buff *skb)
1634{ 1330{
1635#ifdef WLC_HIGH_ONLY
1636 WL_LOCK(wl);
1637#endif
1638 wlc_sendpkt_mac80211(wl->wlc, skb, hw); 1331 wlc_sendpkt_mac80211(wl->wlc, skb, hw);
1639#ifdef WLC_HIGH_ONLY
1640 WL_UNLOCK(wl);
1641#endif
1642 return NETDEV_TX_OK; 1332 return NETDEV_TX_OK;
1643} 1333}
1644 1334
1645void wl_txflowcontrol(wl_info_t *wl, struct wl_if *wlif, bool state, int prio) 1335void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
1336 int prio)
1646{ 1337{
1647 WL_ERROR(("Shouldn't be here %s\n", __func__)); 1338 WL_ERROR("Shouldn't be here %s\n", __func__);
1648} 1339}
1649 1340
1650#if defined(WLC_HIGH_ONLY) 1341void wl_init(struct wl_info *wl)
1651/* Schedule a completion handler to run at safe time */
1652static int
1653wl_schedule_task(wl_info_t *wl, void (*fn) (struct wl_task *task),
1654 void *context)
1655{ 1342{
1656 wl_task_t *task; 1343 WL_TRACE("wl%d: wl_init\n", wl->pub->unit);
1657
1658 WL_TRACE(("wl%d: wl_schedule_task\n", wl->pub->unit));
1659
1660 task = kmalloc(sizeof(wl_task_t), GFP_ATOMIC);
1661 if (!task) {
1662 WL_ERROR(("wl%d: wl_schedule_task: out of memory\n", wl->pub->unit));
1663 return -ENOMEM;
1664 }
1665
1666 INIT_WORK(&task->work, (work_func_t) fn);
1667 task->context = context;
1668
1669 if (!schedule_work(&task->work)) {
1670 WL_ERROR(("wl%d: schedule_work() failed\n", wl->pub->unit));
1671 kfree(task);
1672 return -ENOMEM;
1673 }
1674
1675 atomic_inc(&wl->callbacks);
1676
1677 return 0;
1678}
1679#endif /* defined(WLC_HIGH_ONLY) */
1680
1681void wl_init(wl_info_t *wl)
1682{
1683 WL_TRACE(("wl%d: wl_init\n", wl->pub->unit));
1684 1344
1685 wl_reset(wl); 1345 wl_reset(wl);
1686 1346
1687 wlc_init(wl->wlc); 1347 wlc_init(wl->wlc);
1688} 1348}
1689 1349
1690uint wl_reset(wl_info_t *wl) 1350uint wl_reset(struct wl_info *wl)
1691{ 1351{
1692 WL_TRACE(("wl%d: wl_reset\n", wl->pub->unit)); 1352 WL_TRACE("wl%d: wl_reset\n", wl->pub->unit);
1693 1353
1694 wlc_reset(wl->wlc); 1354 wlc_reset(wl->wlc);
1695 1355
@@ -1703,25 +1363,22 @@ uint wl_reset(wl_info_t *wl)
1703 * These are interrupt on/off entry points. Disable interrupts 1363 * These are interrupt on/off entry points. Disable interrupts
1704 * during interrupt state transition. 1364 * during interrupt state transition.
1705 */ 1365 */
1706void BCMFASTPATH wl_intrson(wl_info_t *wl) 1366void BCMFASTPATH wl_intrson(struct wl_info *wl)
1707{ 1367{
1708#if defined(WLC_LOW)
1709 unsigned long flags; 1368 unsigned long flags;
1710 1369
1711 INT_LOCK(wl, flags); 1370 INT_LOCK(wl, flags);
1712 wlc_intrson(wl->wlc); 1371 wlc_intrson(wl->wlc);
1713 INT_UNLOCK(wl, flags); 1372 INT_UNLOCK(wl, flags);
1714#endif /* WLC_LOW */
1715} 1373}
1716 1374
1717bool wl_alloc_dma_resources(wl_info_t *wl, uint addrwidth) 1375bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
1718{ 1376{
1719 return true; 1377 return true;
1720} 1378}
1721 1379
1722u32 BCMFASTPATH wl_intrsoff(wl_info_t *wl) 1380u32 BCMFASTPATH wl_intrsoff(struct wl_info *wl)
1723{ 1381{
1724#if defined(WLC_LOW)
1725 unsigned long flags; 1382 unsigned long flags;
1726 u32 status; 1383 u32 status;
1727 1384
@@ -1729,23 +1386,18 @@ u32 BCMFASTPATH wl_intrsoff(wl_info_t *wl)
1729 status = wlc_intrsoff(wl->wlc); 1386 status = wlc_intrsoff(wl->wlc);
1730 INT_UNLOCK(wl, flags); 1387 INT_UNLOCK(wl, flags);
1731 return status; 1388 return status;
1732#else
1733 return 0;
1734#endif /* WLC_LOW */
1735} 1389}
1736 1390
1737void wl_intrsrestore(wl_info_t *wl, u32 macintmask) 1391void wl_intrsrestore(struct wl_info *wl, u32 macintmask)
1738{ 1392{
1739#if defined(WLC_LOW)
1740 unsigned long flags; 1393 unsigned long flags;
1741 1394
1742 INT_LOCK(wl, flags); 1395 INT_LOCK(wl, flags);
1743 wlc_intrsrestore(wl->wlc, macintmask); 1396 wlc_intrsrestore(wl->wlc, macintmask);
1744 INT_UNLOCK(wl, flags); 1397 INT_UNLOCK(wl, flags);
1745#endif /* WLC_LOW */
1746} 1398}
1747 1399
1748int wl_up(wl_info_t *wl) 1400int wl_up(struct wl_info *wl)
1749{ 1401{
1750 int error = 0; 1402 int error = 0;
1751 1403
@@ -1757,7 +1409,7 @@ int wl_up(wl_info_t *wl)
1757 return error; 1409 return error;
1758} 1410}
1759 1411
1760void wl_down(wl_info_t *wl) 1412void wl_down(struct wl_info *wl)
1761{ 1413{
1762 uint callbacks, ret_val = 0; 1414 uint callbacks, ret_val = 0;
1763 1415
@@ -1768,24 +1420,21 @@ void wl_down(wl_info_t *wl)
1768 /* wait for down callbacks to complete */ 1420 /* wait for down callbacks to complete */
1769 WL_UNLOCK(wl); 1421 WL_UNLOCK(wl);
1770 1422
1771#ifndef WLC_HIGH_ONLY
1772 /* For HIGH_only driver, it's important to actually schedule other work, 1423 /* For HIGH_only driver, it's important to actually schedule other work,
1773 * not just spin wait since everything runs at schedule level 1424 * not just spin wait since everything runs at schedule level
1774 */ 1425 */
1775 SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000); 1426 SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
1776#endif /* WLC_HIGH_ONLY */
1777 1427
1778 WL_LOCK(wl); 1428 WL_LOCK(wl);
1779} 1429}
1780 1430
1781irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id) 1431irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
1782{ 1432{
1783#if defined(WLC_LOW) 1433 struct wl_info *wl;
1784 wl_info_t *wl;
1785 bool ours, wantdpc; 1434 bool ours, wantdpc;
1786 unsigned long flags; 1435 unsigned long flags;
1787 1436
1788 wl = (wl_info_t *) dev_id; 1437 wl = (struct wl_info *) dev_id;
1789 1438
1790 WL_ISRLOCK(wl, flags); 1439 WL_ISRLOCK(wl, flags);
1791 1440
@@ -1805,17 +1454,13 @@ irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
1805 WL_ISRUNLOCK(wl, flags); 1454 WL_ISRUNLOCK(wl, flags);
1806 1455
1807 return IRQ_RETVAL(ours); 1456 return IRQ_RETVAL(ours);
1808#else
1809 return IRQ_RETVAL(0);
1810#endif /* WLC_LOW */
1811} 1457}
1812 1458
1813static void BCMFASTPATH wl_dpc(unsigned long data) 1459static void BCMFASTPATH wl_dpc(unsigned long data)
1814{ 1460{
1815#ifdef WLC_LOW 1461 struct wl_info *wl;
1816 wl_info_t *wl;
1817 1462
1818 wl = (wl_info_t *) data; 1463 wl = (struct wl_info *) data;
1819 1464
1820 WL_LOCK(wl); 1465 WL_LOCK(wl);
1821 1466
@@ -1846,20 +1491,19 @@ static void BCMFASTPATH wl_dpc(unsigned long data)
1846 1491
1847 done: 1492 done:
1848 WL_UNLOCK(wl); 1493 WL_UNLOCK(wl);
1849#endif /* WLC_LOW */
1850} 1494}
1851 1495
1852static void wl_link_up(wl_info_t *wl, char *ifname) 1496static void wl_link_up(struct wl_info *wl, char *ifname)
1853{ 1497{
1854 WL_ERROR(("wl%d: link up (%s)\n", wl->pub->unit, ifname)); 1498 WL_ERROR("wl%d: link up (%s)\n", wl->pub->unit, ifname);
1855} 1499}
1856 1500
1857static void wl_link_down(wl_info_t *wl, char *ifname) 1501static void wl_link_down(struct wl_info *wl, char *ifname)
1858{ 1502{
1859 WL_ERROR(("wl%d: link down (%s)\n", wl->pub->unit, ifname)); 1503 WL_ERROR("wl%d: link down (%s)\n", wl->pub->unit, ifname);
1860} 1504}
1861 1505
1862void wl_event(wl_info_t *wl, char *ifname, wlc_event_t *e) 1506void wl_event(struct wl_info *wl, char *ifname, wlc_event_t *e)
1863{ 1507{
1864 1508
1865 switch (e->event.event_type) { 1509 switch (e->event.event_type) {
@@ -1877,12 +1521,7 @@ void wl_event(wl_info_t *wl, char *ifname, wlc_event_t *e)
1877 1521
1878static void wl_timer(unsigned long data) 1522static void wl_timer(unsigned long data)
1879{ 1523{
1880#ifndef WLC_HIGH_ONLY
1881 _wl_timer((wl_timer_t *) data); 1524 _wl_timer((wl_timer_t *) data);
1882#else
1883 wl_timer_t *t = (wl_timer_t *) data;
1884 wl_schedule_task(t->wl, wl_timer_task, t);
1885#endif /* WLC_HIGH_ONLY */
1886} 1525}
1887 1526
1888static void _wl_timer(wl_timer_t *t) 1527static void _wl_timer(wl_timer_t *t)
@@ -1906,18 +1545,18 @@ static void _wl_timer(wl_timer_t *t)
1906 WL_UNLOCK(t->wl); 1545 WL_UNLOCK(t->wl);
1907} 1546}
1908 1547
1909wl_timer_t *wl_init_timer(wl_info_t *wl, void (*fn) (void *arg), void *arg, 1548wl_timer_t *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg), void *arg,
1910 const char *name) 1549 const char *name)
1911{ 1550{
1912 wl_timer_t *t; 1551 wl_timer_t *t;
1913 1552
1914 t = kmalloc(sizeof(wl_timer_t), GFP_ATOMIC); 1553 t = kmalloc(sizeof(wl_timer_t), GFP_ATOMIC);
1915 if (!t) { 1554 if (!t) {
1916 WL_ERROR(("wl%d: wl_init_timer: out of memory\n", wl->pub->unit)); 1555 WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl->pub->unit);
1917 return 0; 1556 return 0;
1918 } 1557 }
1919 1558
1920 bzero(t, sizeof(wl_timer_t)); 1559 memset(t, 0, sizeof(wl_timer_t));
1921 1560
1922 init_timer(&t->timer); 1561 init_timer(&t->timer);
1923 t->timer.data = (unsigned long) t; 1562 t->timer.data = (unsigned long) t;
@@ -1940,12 +1579,12 @@ wl_timer_t *wl_init_timer(wl_info_t *wl, void (*fn) (void *arg), void *arg,
1940/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate 1579/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
1941 * as well as it's easier to make it periodic 1580 * as well as it's easier to make it periodic
1942 */ 1581 */
1943void wl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic) 1582void wl_add_timer(struct wl_info *wl, wl_timer_t *t, uint ms, int periodic)
1944{ 1583{
1945#ifdef BCMDBG 1584#ifdef BCMDBG
1946 if (t->set) { 1585 if (t->set) {
1947 WL_ERROR(("%s: Already set. Name: %s, per %d\n", 1586 WL_ERROR("%s: Already set. Name: %s, per %d\n",
1948 __func__, t->name, periodic)); 1587 __func__, t->name, periodic);
1949 } 1588 }
1950#endif 1589#endif
1951 ASSERT(!t->set); 1590 ASSERT(!t->set);
@@ -1960,7 +1599,7 @@ void wl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic)
1960} 1599}
1961 1600
1962/* return true if timer successfully deleted, false if still pending */ 1601/* return true if timer successfully deleted, false if still pending */
1963bool wl_del_timer(wl_info_t *wl, wl_timer_t *t) 1602bool wl_del_timer(struct wl_info *wl, wl_timer_t *t)
1964{ 1603{
1965 if (t->set) { 1604 if (t->set) {
1966 t->set = false; 1605 t->set = false;
@@ -1973,7 +1612,7 @@ bool wl_del_timer(wl_info_t *wl, wl_timer_t *t)
1973 return true; 1612 return true;
1974} 1613}
1975 1614
1976void wl_free_timer(wl_info_t *wl, wl_timer_t *t) 1615void wl_free_timer(struct wl_info *wl, wl_timer_t *t)
1977{ 1616{
1978 wl_timer_t *tmp; 1617 wl_timer_t *tmp;
1979 1618
@@ -2009,7 +1648,7 @@ void wl_free_timer(wl_info_t *wl, wl_timer_t *t)
2009 1648
2010static int wl_linux_watchdog(void *ctx) 1649static int wl_linux_watchdog(void *ctx)
2011{ 1650{
2012 wl_info_t *wl = (wl_info_t *) ctx; 1651 struct wl_info *wl = (struct wl_info *) ctx;
2013 struct net_device_stats *stats = NULL; 1652 struct net_device_stats *stats = NULL;
2014 uint id; 1653 uint id;
2015 /* refresh stats */ 1654 /* refresh stats */
@@ -2049,233 +1688,12 @@ struct wl_fw_hdr {
2049 u32 idx; 1688 u32 idx;
2050}; 1689};
2051 1690
2052#ifdef WLC_HIGH_ONLY
2053static void wl_rpc_down(void *wlh)
2054{
2055 wl_info_t *wl = (wl_info_t *) (wlh);
2056
2057 wlc_device_removed(wl->wlc);
2058
2059 wl_rpcq_free(wl);
2060}
2061
2062static int BCMFASTPATH wl_start(struct sk_buff *skb, wl_info_t *wl)
2063{
2064
2065 unsigned long flags;
2066
2067 skb->prev = NULL;
2068
2069 /* Lock the queue as tasklet could be running at this time */
2070 TXQ_LOCK(wl, flags);
2071 if (wl->txq_head == NULL)
2072 wl->txq_head = skb;
2073 else {
2074 wl->txq_tail->prev = skb;
2075 }
2076 wl->txq_tail = skb;
2077
2078 if (wl->txq_dispatched == false) {
2079 wl->txq_dispatched = true;
2080
2081 if (schedule_work(&wl->txq_task.work)) {
2082 atomic_inc(&wl->callbacks);
2083 } else {
2084 WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
2085 wl->pub->unit));
2086 }
2087 }
2088
2089 TXQ_UNLOCK(wl, flags);
2090
2091 return 0;
2092
2093}
2094
2095static void wl_start_txqwork(struct wl_task *task)
2096{
2097 wl_info_t *wl = (wl_info_t *) task->context;
2098 struct sk_buff *skb;
2099 unsigned long flags;
2100 uint count = 0;
2101
2102 WL_TRACE(("wl%d: wl_start_txqwork\n", wl->pub->unit));
2103
2104 /* First remove an entry then go for execution */
2105 TXQ_LOCK(wl, flags);
2106 while (wl->txq_head) {
2107 skb = wl->txq_head;
2108 wl->txq_head = skb->prev;
2109 skb->prev = NULL;
2110 if (wl->txq_head == NULL)
2111 wl->txq_tail = NULL;
2112 TXQ_UNLOCK(wl, flags);
2113
2114 /* it has WL_LOCK/WL_UNLOCK inside */
2115 wl_start_int(wl, WL_TO_HW(wl), skb);
2116
2117 /* bounded our execution, reshedule ourself next */
2118 if (++count >= 10)
2119 break;
2120
2121 TXQ_LOCK(wl, flags);
2122 }
2123
2124 if (count >= 10) {
2125 if (!schedule_work(&wl->txq_task.work)) {
2126 WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
2127 wl->pub->unit));
2128 atomic_dec(&wl->callbacks);
2129 }
2130 } else {
2131 wl->txq_dispatched = false;
2132 TXQ_UNLOCK(wl, flags);
2133 atomic_dec(&wl->callbacks);
2134 }
2135
2136 return;
2137}
2138
2139static void wl_txq_free(wl_info_t *wl)
2140{
2141 struct sk_buff *skb;
2142
2143 if (wl->txq_head == NULL) {
2144 ASSERT(wl->txq_tail == NULL);
2145 return;
2146 }
2147
2148 while (wl->txq_head) {
2149 skb = wl->txq_head;
2150 wl->txq_head = skb->prev;
2151 PKTFREE(wl->osh, skb, true);
2152 }
2153
2154 wl->txq_tail = NULL;
2155}
2156
2157static void wl_rpcq_free(wl_info_t *wl)
2158{
2159 rpc_buf_t *buf;
2160
2161 if (wl->rpcq_head == NULL) {
2162 ASSERT(wl->rpcq_tail == NULL);
2163 return;
2164 }
2165
2166 while (wl->rpcq_head) {
2167 buf = wl->rpcq_head;
2168 wl->rpcq_head = bcm_rpc_buf_next_get(wl->rpc_th, buf);
2169 bcm_rpc_buf_free(wl->rpc_dispatch_ctx.rpc, buf);
2170 }
2171
2172 wl->rpcq_tail = NULL;
2173}
2174
2175static void wl_rpcq_dispatch(struct wl_task *task)
2176{
2177 wl_info_t *wl = (wl_info_t *) task->context;
2178 rpc_buf_t *buf;
2179 unsigned long flags;
2180
2181 /* First remove an entry then go for execution */
2182 RPCQ_LOCK(wl, flags);
2183 while (wl->rpcq_head) {
2184 buf = wl->rpcq_head;
2185 wl->rpcq_head = bcm_rpc_buf_next_get(wl->rpc_th, buf);
2186
2187 if (wl->rpcq_head == NULL)
2188 wl->rpcq_tail = NULL;
2189 RPCQ_UNLOCK(wl, flags);
2190
2191 WL_LOCK(wl);
2192 wlc_rpc_high_dispatch(&wl->rpc_dispatch_ctx, buf);
2193 WL_UNLOCK(wl);
2194
2195 RPCQ_LOCK(wl, flags);
2196 }
2197
2198 wl->rpcq_dispatched = false;
2199
2200 RPCQ_UNLOCK(wl, flags);
2201
2202 kfree(task);
2203 atomic_dec(&wl->callbacks);
2204}
2205
2206static void wl_rpcq_add(wl_info_t *wl, rpc_buf_t *buf)
2207{
2208 unsigned long flags;
2209
2210 bcm_rpc_buf_next_set(wl->rpc_th, buf, NULL);
2211
2212 /* Lock the queue as tasklet could be running at this time */
2213 RPCQ_LOCK(wl, flags);
2214 if (wl->rpcq_head == NULL)
2215 wl->rpcq_head = buf;
2216 else
2217 bcm_rpc_buf_next_set(wl->rpc_th, wl->rpcq_tail, buf);
2218
2219 wl->rpcq_tail = buf;
2220
2221 if (wl->rpcq_dispatched == false) {
2222 wl->rpcq_dispatched = true;
2223 wl_schedule_task(wl, wl_rpcq_dispatch, wl);
2224 }
2225
2226 RPCQ_UNLOCK(wl, flags);
2227}
2228
2229#if defined(BCMDBG)
2230static const struct name_entry rpc_name_tbl[] = RPC_ID_TABLE;
2231#endif /* BCMDBG */
2232
2233/* dongle-side rpc dispatch routine */
2234static void wl_rpc_dispatch_schedule(void *ctx, struct rpc_buf *buf)
2235{
2236 bcm_xdr_buf_t b;
2237 wl_info_t *wl = (wl_info_t *) ctx;
2238 wlc_rpc_id_t rpc_id;
2239 int err;
2240
2241 bcm_xdr_buf_init(&b, bcm_rpc_buf_data(wl->rpc_th, buf),
2242 bcm_rpc_buf_len_get(wl->rpc_th, buf));
2243
2244 err = bcm_xdr_unpack_u32(&b, &rpc_id);
2245 ASSERT(!err);
2246 WL_TRACE(("%s: Dispatch id %s\n", __func__,
2247 WLC_RPC_ID_LOOKUP(rpc_name_tbl, rpc_id)));
2248
2249 /* Handle few emergency ones */
2250 switch (rpc_id) {
2251 default:
2252 wl_rpcq_add(wl, buf);
2253 break;
2254 }
2255}
2256
2257static void wl_timer_task(wl_task_t *task)
2258{
2259 wl_timer_t *t = (wl_timer_t *) task->context;
2260
2261 _wl_timer(t);
2262 kfree(task);
2263
2264 /* This dec is for the task_schedule. The timer related
2265 * callback is decremented in _wl_timer
2266 */
2267 atomic_dec(&t->wl->callbacks);
2268}
2269#endif /* WLC_HIGH_ONLY */
2270
2271#ifndef WLC_HIGH_ONLY
2272char *wl_firmwares[WL_MAX_FW] = { 1691char *wl_firmwares[WL_MAX_FW] = {
2273 "brcm/bcm43xx", 1692 "brcm/bcm43xx",
2274 NULL 1693 NULL
2275}; 1694};
2276 1695
2277#ifdef WLC_LOW 1696int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
2278int wl_ucode_init_buf(wl_info_t *wl, void **pbuf, u32 idx)
2279{ 1697{
2280 int i, entry; 1698 int i, entry;
2281 const u8 *pdata; 1699 const u8 *pdata;
@@ -2301,7 +1719,7 @@ int wl_ucode_init_buf(wl_info_t *wl, void **pbuf, u32 idx)
2301 return -1; 1719 return -1;
2302} 1720}
2303 1721
2304int wl_ucode_init_uint(wl_info_t *wl, u32 *data, u32 idx) 1722int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
2305{ 1723{
2306 int i, entry; 1724 int i, entry;
2307 const u8 *pdata; 1725 const u8 *pdata;
@@ -2321,22 +1739,21 @@ int wl_ucode_init_uint(wl_info_t *wl, u32 *data, u32 idx)
2321 printf("ERROR: ucode tag:%d can not be found!\n", idx); 1739 printf("ERROR: ucode tag:%d can not be found!\n", idx);
2322 return -1; 1740 return -1;
2323} 1741}
2324#endif /* WLC_LOW */
2325 1742
2326static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev) 1743static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
2327{ 1744{
2328 int status; 1745 int status;
2329 struct device *device = &pdev->dev; 1746 struct device *device = &pdev->dev;
2330 char fw_name[100]; 1747 char fw_name[100];
2331 int i; 1748 int i;
2332 1749
2333 bzero((void *)&wl->fw, sizeof(struct wl_firmware)); 1750 memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
2334 for (i = 0; i < WL_MAX_FW; i++) { 1751 for (i = 0; i < WL_MAX_FW; i++) {
2335 if (wl_firmwares[i] == NULL) 1752 if (wl_firmwares[i] == NULL)
2336 break; 1753 break;
2337 sprintf(fw_name, "%s-%d.fw", wl_firmwares[i], 1754 sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
2338 UCODE_LOADER_API_VER); 1755 UCODE_LOADER_API_VER);
2339 WL_NONE(("request fw %s\n", fw_name)); 1756 WL_NONE("request fw %s\n", fw_name);
2340 status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); 1757 status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
2341 if (status) { 1758 if (status) {
2342 printf("%s: fail to load firmware %s\n", 1759 printf("%s: fail to load firmware %s\n",
@@ -2344,7 +1761,7 @@ static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev)
2344 wl_release_fw(wl); 1761 wl_release_fw(wl);
2345 return status; 1762 return status;
2346 } 1763 }
2347 WL_NONE(("request fw %s\n", fw_name)); 1764 WL_NONE("request fw %s\n", fw_name);
2348 sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i], 1765 sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
2349 UCODE_LOADER_API_VER); 1766 UCODE_LOADER_API_VER);
2350 status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); 1767 status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
@@ -2356,22 +1773,19 @@ static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev)
2356 } 1773 }
2357 wl->fw.hdr_num_entries[i] = 1774 wl->fw.hdr_num_entries[i] =
2358 wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr)); 1775 wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
2359 WL_NONE(("request fw %s find: %d entries\n", fw_name, 1776 WL_NONE("request fw %s find: %d entries\n",
2360 wl->fw.hdr_num_entries[i])); 1777 fw_name, wl->fw.hdr_num_entries[i]);
2361 } 1778 }
2362 wl->fw.fw_cnt = i; 1779 wl->fw.fw_cnt = i;
2363 wl_ucode_data_init(wl); 1780 return wl_ucode_data_init(wl);
2364 return 0;
2365} 1781}
2366 1782
2367#ifdef WLC_LOW
2368void wl_ucode_free_buf(void *p) 1783void wl_ucode_free_buf(void *p)
2369{ 1784{
2370 kfree(p); 1785 kfree(p);
2371} 1786}
2372#endif /* WLC_LOW */
2373 1787
2374static void wl_release_fw(wl_info_t *wl) 1788static void wl_release_fw(struct wl_info *wl)
2375{ 1789{
2376 int i; 1790 int i;
2377 for (i = 0; i < WL_MAX_FW; i++) { 1791 for (i = 0; i < WL_MAX_FW; i++) {
@@ -2379,4 +1793,54 @@ static void wl_release_fw(wl_info_t *wl)
2379 release_firmware(wl->fw.fw_hdr[i]); 1793 release_firmware(wl->fw.fw_hdr[i]);
2380 } 1794 }
2381} 1795}
2382#endif /* WLC_HIGH_ONLY */ 1796
1797
1798/*
1799 * checks validity of all firmware images loaded from user space
1800 */
1801int wl_check_firmwares(struct wl_info *wl)
1802{
1803 int i;
1804 int entry;
1805 int rc = 0;
1806 const struct firmware *fw;
1807 const struct firmware *fw_hdr;
1808 struct wl_fw_hdr *ucode_hdr;
1809 for (i = 0; i < WL_MAX_FW && rc == 0; i++) {
1810 fw = wl->fw.fw_bin[i];
1811 fw_hdr = wl->fw.fw_hdr[i];
1812 if (fw == NULL && fw_hdr == NULL) {
1813 break;
1814 } else if (fw == NULL || fw_hdr == NULL) {
1815 WL_ERROR("%s: invalid bin/hdr fw\n", __func__);
1816 rc = -EBADF;
1817 } else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
1818 WL_ERROR("%s: non integral fw hdr file size %d/%zu\n",
1819 __func__, fw_hdr->size,
1820 sizeof(struct wl_fw_hdr));
1821 rc = -EBADF;
1822 } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
1823 WL_ERROR("%s: out of bounds fw file size %d\n",
1824 __func__, fw->size);
1825 rc = -EBADF;
1826 } else {
1827 /* check if ucode section overruns firmware image */
1828 ucode_hdr = (struct wl_fw_hdr *)fw_hdr->data;
1829 for (entry = 0; entry < wl->fw.hdr_num_entries[i] && rc;
1830 entry++, ucode_hdr++) {
1831 if (ucode_hdr->offset + ucode_hdr->len >
1832 fw->size) {
1833 WL_ERROR("%s: conflicting bin/hdr\n",
1834 __func__);
1835 rc = -EBADF;
1836 }
1837 }
1838 }
1839 }
1840 if (rc == 0 && wl->fw.fw_cnt != i) {
1841 WL_ERROR("%s: invalid fw_cnt=%d\n", __func__, wl->fw.fw_cnt);
1842 rc = -EBADF;
1843 }
1844 return rc;
1845}
1846