2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #define __UNDEF_NO_VERSION__
19 #include <linux/kernel.h>
20 #include <linux/etherdevice.h>
21 #include <linux/string.h>
22 #include <linux/pci_ids.h>
24 #include <linux/module.h>
25 #include <linux/pci.h>
26 #include <linux/sched.h>
28 #define WLC_MAXBSSCFG 1 /* single BSS configs */
31 #include <net/mac80211.h>
32 #include <phy_version.h>
39 #include <wlc_channel.h>
43 #include <wl_export.h>
45 #include <wl_mac80211.h>
46 #include <linux/firmware.h>
48 #include <d11ucode_ext.h>
51 static void wl_timer(unsigned long data
);
52 static void _wl_timer(wl_timer_t
*t
);
55 static int ieee_hw_init(struct ieee80211_hw
*hw
);
56 static int ieee_hw_rate_init(struct ieee80211_hw
*hw
);
58 static int wl_linux_watchdog(void *ctx
);
60 /* Flags we support */
61 #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
67 FIF_BCN_PRBRESP_PROMISC)
71 struct ieee80211_tkip_data
{
72 #define TKIP_KEY_LEN 32
88 u32 dot11RSNAStatsTKIPReplays
;
89 u32 dot11RSNAStatsTKIPICVErrors
;
90 u32 dot11RSNAStatsTKIPLocalMICFailures
;
94 struct crypto_tfm
*tfm_arc4
;
95 struct crypto_tfm
*tfm_michael
;
97 /* scratch buffers for virt_to_page() (crypto API) */
98 u8 rx_hdr
[16], tx_hdr
[16];
101 #define WL_DEV_IF(dev) ((struct wl_if *)netdev_priv(dev))
102 #define WL_INFO(dev) ((struct wl_info *)(WL_DEV_IF(dev)->wl))
103 static int wl_request_fw(struct wl_info
*wl
, struct pci_dev
*pdev
);
104 static void wl_release_fw(struct wl_info
*wl
);
106 /* local prototypes */
107 static int wl_start(struct sk_buff
*skb
, struct wl_info
*wl
);
108 static int wl_start_int(struct wl_info
*wl
, struct ieee80211_hw
*hw
,
109 struct sk_buff
*skb
);
110 static void wl_dpc(unsigned long data
);
112 MODULE_AUTHOR("Broadcom Corporation");
113 MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
114 MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
115 MODULE_LICENSE("Dual BSD/GPL");
117 /* recognized PCI IDs */
118 static struct pci_device_id wl_id_table
[] = {
119 {PCI_VENDOR_ID_BROADCOM
, 0x4357, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0}, /* 43225 2G */
120 {PCI_VENDOR_ID_BROADCOM
, 0x4353, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0}, /* 43224 DUAL */
121 {PCI_VENDOR_ID_BROADCOM
, 0x4727, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0}, /* 4313 DUAL */
125 MODULE_DEVICE_TABLE(pci
, wl_id_table
);
126 static void wl_remove(struct pci_dev
*pdev
);
130 static int msglevel
= 0xdeadbeef;
131 module_param(msglevel
, int, 0);
132 static int phymsglevel
= 0xdeadbeef;
133 module_param(phymsglevel
, int, 0);
136 #define HW_TO_WL(hw) (hw->priv)
137 #define WL_TO_HW(wl) (wl->pub->ieee_hw)
138 static int wl_ops_tx(struct ieee80211_hw
*hw
, struct sk_buff
*skb
);
139 static int wl_ops_start(struct ieee80211_hw
*hw
);
140 static void wl_ops_stop(struct ieee80211_hw
*hw
);
141 static int wl_ops_add_interface(struct ieee80211_hw
*hw
,
142 struct ieee80211_vif
*vif
);
143 static void wl_ops_remove_interface(struct ieee80211_hw
*hw
,
144 struct ieee80211_vif
*vif
);
145 static int wl_ops_config(struct ieee80211_hw
*hw
, u32 changed
);
146 static void wl_ops_bss_info_changed(struct ieee80211_hw
*hw
,
147 struct ieee80211_vif
*vif
,
148 struct ieee80211_bss_conf
*info
,
150 static void wl_ops_configure_filter(struct ieee80211_hw
*hw
,
151 unsigned int changed_flags
,
152 unsigned int *total_flags
, u64 multicast
);
153 static int wl_ops_set_tim(struct ieee80211_hw
*hw
, struct ieee80211_sta
*sta
,
155 static void wl_ops_sw_scan_start(struct ieee80211_hw
*hw
);
156 static void wl_ops_sw_scan_complete(struct ieee80211_hw
*hw
);
157 static void wl_ops_set_tsf(struct ieee80211_hw
*hw
, u64 tsf
);
158 static int wl_ops_get_stats(struct ieee80211_hw
*hw
,
159 struct ieee80211_low_level_stats
*stats
);
160 static int wl_ops_set_rts_threshold(struct ieee80211_hw
*hw
, u32 value
);
161 static void wl_ops_sta_notify(struct ieee80211_hw
*hw
,
162 struct ieee80211_vif
*vif
,
163 enum sta_notify_cmd cmd
,
164 struct ieee80211_sta
*sta
);
165 static int wl_ops_conf_tx(struct ieee80211_hw
*hw
, u16 queue
,
166 const struct ieee80211_tx_queue_params
*params
);
167 static u64
wl_ops_get_tsf(struct ieee80211_hw
*hw
);
168 static int wl_sta_add(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
169 struct ieee80211_sta
*sta
);
170 static int wl_sta_remove(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
171 struct ieee80211_sta
*sta
);
172 static int wl_ampdu_action(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
173 enum ieee80211_ampdu_mlme_action action
,
174 struct ieee80211_sta
*sta
, u16 tid
, u16
*ssn
);
176 static int wl_ops_tx(struct ieee80211_hw
*hw
, struct sk_buff
*skb
)
179 struct wl_info
*wl
= hw
->priv
;
182 WL_ERROR("ops->tx called while down\n");
186 status
= wl_start(skb
, wl
);
192 static int wl_ops_start(struct ieee80211_hw
*hw
)
194 struct wl_info
*wl
= hw
->priv
;
196 struct ieee80211_channel *curchan = hw->conf.channel;
197 WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
201 ieee80211_wake_queues(hw
);
207 static void wl_ops_stop(struct ieee80211_hw
*hw
)
209 struct wl_info
*wl
= hw
->priv
;
213 ieee80211_stop_queues(hw
);
220 wl_ops_add_interface(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
)
225 /* Just STA for now */
226 if (vif
->type
!= NL80211_IFTYPE_AP
&&
227 vif
->type
!= NL80211_IFTYPE_MESH_POINT
&&
228 vif
->type
!= NL80211_IFTYPE_STATION
&&
229 vif
->type
!= NL80211_IFTYPE_WDS
&&
230 vif
->type
!= NL80211_IFTYPE_ADHOC
) {
231 WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
232 __func__
, vif
->type
);
242 WL_ERROR("%s: wl_up() returned %d\n", __func__
, err
);
247 wl_ops_remove_interface(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
)
253 ieee_set_channel(struct ieee80211_hw
*hw
, struct ieee80211_channel
*chan
,
254 enum nl80211_channel_type type
)
256 struct wl_info
*wl
= HW_TO_WL(hw
);
260 case NL80211_CHAN_HT20
:
261 case NL80211_CHAN_NO_HT
:
263 err
= wlc_set(wl
->wlc
, WLC_SET_CHANNEL
, chan
->hw_value
);
266 case NL80211_CHAN_HT40MINUS
:
267 case NL80211_CHAN_HT40PLUS
:
268 WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__
);
277 static int wl_ops_config(struct ieee80211_hw
*hw
, u32 changed
)
279 struct ieee80211_conf
*conf
= &hw
->conf
;
280 struct wl_info
*wl
= HW_TO_WL(hw
);
284 if (changed
& IEEE80211_CONF_CHANGE_LISTEN_INTERVAL
) {
285 WL_NONE("%s: Setting listen interval to %d\n",
286 __func__
, conf
->listen_interval
);
288 (wl
->wlc
, "bcn_li_bcn", conf
->listen_interval
)) {
289 WL_ERROR("%s: Error setting listen_interval\n",
294 wlc_iovar_getint(wl
->wlc
, "bcn_li_bcn", &new_int
);
295 ASSERT(new_int
== conf
->listen_interval
);
297 if (changed
& IEEE80211_CONF_CHANGE_MONITOR
)
298 WL_NONE("Need to set monitor mode\n");
299 if (changed
& IEEE80211_CONF_CHANGE_PS
)
300 WL_NONE("Need to set Power-save mode\n");
302 if (changed
& IEEE80211_CONF_CHANGE_POWER
) {
303 WL_NONE("%s: Setting tx power to %d dbm\n",
304 __func__
, conf
->power_level
);
306 (wl
->wlc
, "qtxpower", conf
->power_level
* 4)) {
307 WL_ERROR("%s: Error setting power_level\n", __func__
);
311 wlc_iovar_getint(wl
->wlc
, "qtxpower", &new_int
);
312 if (new_int
!= (conf
->power_level
* 4))
313 WL_ERROR("%s: Power level req != actual, %d %d\n",
314 __func__
, conf
->power_level
* 4, new_int
);
316 if (changed
& IEEE80211_CONF_CHANGE_CHANNEL
) {
317 err
= ieee_set_channel(hw
, conf
->channel
, conf
->channel_type
);
319 if (changed
& IEEE80211_CONF_CHANGE_RETRY_LIMITS
) {
320 WL_NONE("%s: srl %d, lrl %d\n",
322 conf
->short_frame_max_tx_count
,
323 conf
->long_frame_max_tx_count
);
325 (wl
->wlc
, WLC_SET_SRL
,
326 conf
->short_frame_max_tx_count
) < 0) {
327 WL_ERROR("%s: Error setting srl\n", __func__
);
331 if (wlc_set(wl
->wlc
, WLC_SET_LRL
, conf
->long_frame_max_tx_count
)
333 WL_ERROR("%s: Error setting lrl\n", __func__
);
344 wl_ops_bss_info_changed(struct ieee80211_hw
*hw
,
345 struct ieee80211_vif
*vif
,
346 struct ieee80211_bss_conf
*info
, u32 changed
)
348 struct wl_info
*wl
= HW_TO_WL(hw
);
352 if (changed
& BSS_CHANGED_ASSOC
) {
353 WL_ERROR("Associated:\t%s\n", info
->assoc
? "True" : "False");
354 /* association status changed (associated/disassociated)
355 * also implies a change in the AID.
358 if (changed
& BSS_CHANGED_ERP_CTS_PROT
) {
359 WL_NONE("Use_cts_prot:\t%s Implement me\n",
360 info
->use_cts_prot
? "True" : "False");
361 /* CTS protection changed */
363 if (changed
& BSS_CHANGED_ERP_PREAMBLE
) {
364 WL_NONE("Short preamble:\t%s Implement me\n",
365 info
->use_short_preamble
? "True" : "False");
366 /* preamble changed */
368 if (changed
& BSS_CHANGED_ERP_SLOT
) {
369 WL_NONE("Changing short slot:\t%s\n",
370 info
->use_short_slot
? "True" : "False");
371 if (info
->use_short_slot
)
375 wlc_set(wl
->wlc
, WLC_SET_SHORTSLOT_OVERRIDE
, val
);
376 /* slot timing changed */
379 if (changed
& BSS_CHANGED_HT
) {
380 WL_NONE("%s: HT mode - Implement me\n", __func__
);
381 /* 802.11n parameters changed */
383 if (changed
& BSS_CHANGED_BASIC_RATES
) {
384 WL_NONE("Need to change Basic Rates:\t0x%x! Implement me\n",
385 (u32
) info
->basic_rates
);
386 /* Basic rateset changed */
388 if (changed
& BSS_CHANGED_BEACON_INT
) {
389 WL_NONE("Beacon Interval:\t%d Implement me\n",
391 /* Beacon interval changed */
393 if (changed
& BSS_CHANGED_BSSID
) {
394 WL_NONE("new BSSID:\taid %d bss:%pM\n",
395 info
->aid
, info
->bssid
);
396 /* BSSID changed, for whatever reason (IBSS and managed mode) */
397 /* FIXME: need to store bssid in bsscfg */
398 wlc_set_addrmatch(wl
->wlc
, RCM_BSSID_OFFSET
,
399 (struct ether_addr
*)info
->bssid
);
401 if (changed
& BSS_CHANGED_BEACON
) {
402 WL_ERROR("BSS_CHANGED_BEACON\n");
403 /* Beacon data changed, retrieve new beacon (beaconing modes) */
405 if (changed
& BSS_CHANGED_BEACON_ENABLED
) {
406 WL_ERROR("Beacon enabled:\t%s\n",
407 info
->enable_beacon
? "True" : "False");
408 /* Beaconing should be enabled/disabled (beaconing modes) */
414 wl_ops_configure_filter(struct ieee80211_hw
*hw
,
415 unsigned int changed_flags
,
416 unsigned int *total_flags
, u64 multicast
)
418 struct wl_info
*wl
= hw
->priv
;
420 changed_flags
&= MAC_FILTERS
;
421 *total_flags
&= MAC_FILTERS
;
422 if (changed_flags
& FIF_PROMISC_IN_BSS
)
423 WL_ERROR("FIF_PROMISC_IN_BSS\n");
424 if (changed_flags
& FIF_ALLMULTI
)
425 WL_ERROR("FIF_ALLMULTI\n");
426 if (changed_flags
& FIF_FCSFAIL
)
427 WL_ERROR("FIF_FCSFAIL\n");
428 if (changed_flags
& FIF_PLCPFAIL
)
429 WL_ERROR("FIF_PLCPFAIL\n");
430 if (changed_flags
& FIF_CONTROL
)
431 WL_ERROR("FIF_CONTROL\n");
432 if (changed_flags
& FIF_OTHER_BSS
)
433 WL_ERROR("FIF_OTHER_BSS\n");
434 if (changed_flags
& FIF_BCN_PRBRESP_PROMISC
) {
435 WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
437 if (*total_flags
& FIF_BCN_PRBRESP_PROMISC
) {
438 wl
->pub
->mac80211_state
|= MAC80211_PROMISC_BCNS
;
439 wlc_mac_bcn_promisc_change(wl
->wlc
, 1);
441 wlc_mac_bcn_promisc_change(wl
->wlc
, 0);
442 wl
->pub
->mac80211_state
&= ~MAC80211_PROMISC_BCNS
;
450 wl_ops_set_tim(struct ieee80211_hw
*hw
, struct ieee80211_sta
*sta
, bool set
)
452 WL_ERROR("%s: Enter\n", __func__
);
456 static void wl_ops_sw_scan_start(struct ieee80211_hw
*hw
)
458 WL_NONE("Scan Start\n");
462 static void wl_ops_sw_scan_complete(struct ieee80211_hw
*hw
)
464 WL_NONE("Scan Complete\n");
468 static void wl_ops_set_tsf(struct ieee80211_hw
*hw
, u64 tsf
)
470 WL_ERROR("%s: Enter\n", __func__
);
475 wl_ops_get_stats(struct ieee80211_hw
*hw
,
476 struct ieee80211_low_level_stats
*stats
)
478 WL_ERROR("%s: Enter\n", __func__
);
482 static int wl_ops_set_rts_threshold(struct ieee80211_hw
*hw
, u32 value
)
484 WL_ERROR("%s: Enter\n", __func__
);
489 wl_ops_sta_notify(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
490 enum sta_notify_cmd cmd
, struct ieee80211_sta
*sta
)
492 WL_NONE("%s: Enter\n", __func__
);
495 WL_ERROR("%s: Unknown cmd = %d\n", __func__
, cmd
);
502 wl_ops_conf_tx(struct ieee80211_hw
*hw
, u16 queue
,
503 const struct ieee80211_tx_queue_params
*params
)
505 struct wl_info
*wl
= hw
->priv
;
507 WL_NONE("%s: Enter (WME config)\n", __func__
);
508 WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue
,
509 params
->txop
, params
->cw_min
, params
->cw_max
, params
->aifs
);
512 wlc_wme_setparams(wl
->wlc
, queue
, (void *)params
, true);
518 static u64
wl_ops_get_tsf(struct ieee80211_hw
*hw
)
520 WL_ERROR("%s: Enter\n", __func__
);
525 wl_sta_add(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
526 struct ieee80211_sta
*sta
)
531 struct wl_info
*wl
= hw
->priv
;
534 scb
= (struct scb
*)sta
->drv_priv
;
535 memset(scb
, 0, sizeof(struct scb
));
536 for (i
= 0; i
< NUMPRIO
; i
++)
537 scb
->seqctl
[i
] = 0xFFFF;
538 scb
->seqctl_nonqos
= 0xFFFF;
539 scb
->magic
= SCB_MAGIC
;
541 wl
->pub
->global_scb
= scb
;
542 wl
->pub
->global_ampdu
= &(scb
->scb_ampdu
);
543 wl
->pub
->global_ampdu
->scb
= scb
;
544 wl
->pub
->global_ampdu
->max_pdu
= 16;
545 pktq_init(&scb
->scb_ampdu
.txq
, AMPDU_MAX_SCB_TID
,
546 AMPDU_MAX_SCB_TID
* PKTQ_LEN_DEFAULT
);
548 sta
->ht_cap
.ht_supported
= true;
549 sta
->ht_cap
.ampdu_factor
= AMPDU_RX_FACTOR_64K
;
550 sta
->ht_cap
.ampdu_density
= AMPDU_DEF_MPDU_DENSITY
;
551 sta
->ht_cap
.cap
= IEEE80211_HT_CAP_GRN_FLD
|
552 IEEE80211_HT_CAP_SGI_20
|
553 IEEE80211_HT_CAP_SGI_40
| IEEE80211_HT_CAP_40MHZ_INTOLERANT
;
555 /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
560 wl_sta_remove(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
561 struct ieee80211_sta
*sta
)
563 WL_NONE("%s: Enter\n", __func__
);
568 wl_ampdu_action(struct ieee80211_hw
*hw
,
569 struct ieee80211_vif
*vif
,
570 enum ieee80211_ampdu_mlme_action action
,
571 struct ieee80211_sta
*sta
, u16 tid
, u16
*ssn
)
574 struct scb
*scb
= (struct scb
*)sta
->drv_priv
;
576 struct wl_info
*wl
= hw
->priv
;
578 ASSERT(scb
->magic
== SCB_MAGIC
);
580 case IEEE80211_AMPDU_RX_START
:
581 WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__
);
583 case IEEE80211_AMPDU_RX_STOP
:
584 WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__
);
586 case IEEE80211_AMPDU_TX_START
:
587 if (!wlc_aggregatable(wl
->wlc
, tid
)) {
588 /* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
591 /* XXX: Use the starting sequence number provided ... */
593 ieee80211_start_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
596 case IEEE80211_AMPDU_TX_STOP
:
597 ieee80211_stop_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
599 case IEEE80211_AMPDU_TX_OPERATIONAL
:
600 /* Not sure what to do here */
601 /* Power save wakeup */
602 WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
606 WL_ERROR("%s: Invalid command, ignoring\n", __func__
);
612 static const struct ieee80211_ops wl_ops
= {
614 .start
= wl_ops_start
,
616 .add_interface
= wl_ops_add_interface
,
617 .remove_interface
= wl_ops_remove_interface
,
618 .config
= wl_ops_config
,
619 .bss_info_changed
= wl_ops_bss_info_changed
,
620 .configure_filter
= wl_ops_configure_filter
,
621 .set_tim
= wl_ops_set_tim
,
622 .sw_scan_start
= wl_ops_sw_scan_start
,
623 .sw_scan_complete
= wl_ops_sw_scan_complete
,
624 .set_tsf
= wl_ops_set_tsf
,
625 .get_stats
= wl_ops_get_stats
,
626 .set_rts_threshold
= wl_ops_set_rts_threshold
,
627 .sta_notify
= wl_ops_sta_notify
,
628 .conf_tx
= wl_ops_conf_tx
,
629 .get_tsf
= wl_ops_get_tsf
,
630 .sta_add
= wl_sta_add
,
631 .sta_remove
= wl_sta_remove
,
632 .ampdu_action
= wl_ampdu_action
,
635 static int wl_set_hint(struct wl_info
*wl
, char *abbrev
)
637 WL_ERROR("%s: Sending country code %c%c to MAC80211\n",
638 __func__
, abbrev
[0], abbrev
[1]);
639 return regulatory_hint(wl
->pub
->ieee_hw
->wiphy
, abbrev
);
643 * attach to the WL device.
645 * Attach to the WL device identified by vendor and device parameters.
646 * regs is a host accessible memory address pointing to WL device registers.
648 * wl_attach is not defined as static because in the case where no bus
649 * is defined, wl_attach will never be called, and thus, gcc will issue
650 * a warning that this function is defined but not used if we declare
653 static struct wl_info
*wl_attach(u16 vendor
, u16 device
, unsigned long regs
,
654 uint bustype
, void *btparam
, uint irq
)
657 struct osl_info
*osh
;
660 unsigned long base_addr
;
661 struct ieee80211_hw
*hw
;
668 WL_ERROR("wl%d: unit number overflow, exiting\n", unit
);
672 osh
= osl_attach(btparam
, bustype
);
675 /* allocate private info */
676 hw
= pci_get_drvdata(btparam
); /* btparam == pdev */
681 atomic_set(&wl
->callbacks
, 0);
683 /* setup the bottom half handler */
684 tasklet_init(&wl
->tasklet
, wl_dpc
, (unsigned long) wl
);
690 if (bustype
== PCI_BUS
) {
692 } else if (bustype
== RPC_BUS
) {
696 WL_TRACE("force to PCI\n");
698 wl
->bcm_bustype
= bustype
;
700 wl
->regsva
= ioremap_nocache(base_addr
, PCI_BAR0_WINSZ
);
701 if (wl
->regsva
== NULL
) {
702 WL_ERROR("wl%d: ioremap() failed\n", unit
);
705 spin_lock_init(&wl
->lock
);
706 spin_lock_init(&wl
->isr_lock
);
709 if (wl_request_fw(wl
, (struct pci_dev
*)btparam
)) {
710 printf("%s: Failed to find firmware usually in %s\n",
711 KBUILD_MODNAME
, "/lib/firmware/brcm");
713 wl_remove((struct pci_dev
*)btparam
);
717 /* common load-time initialization */
718 wl
->wlc
= wlc_attach((void *)wl
, vendor
, device
, unit
, wl
->piomode
, osh
,
719 wl
->regsva
, wl
->bcm_bustype
, btparam
, &err
);
722 printf("%s: wlc_attach() failed with code %d\n",
723 KBUILD_MODNAME
, err
);
726 wl
->pub
= wlc_pub(wl
->wlc
);
728 wl
->pub
->ieee_hw
= hw
;
729 ASSERT(wl
->pub
->ieee_hw
);
730 ASSERT(wl
->pub
->ieee_hw
->priv
== wl
);
733 if (wlc_iovar_setint(wl
->wlc
, "mpc", 0)) {
734 WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit
);
737 /* register our interrupt handler */
738 if (request_irq(irq
, wl_isr
, IRQF_SHARED
, KBUILD_MODNAME
, wl
)) {
739 WL_ERROR("wl%d: request_irq() failed\n", unit
);
744 /* register module */
745 wlc_module_register(wl
->pub
, NULL
, "linux", wl
, NULL
, wl_linux_watchdog
,
748 if (ieee_hw_init(hw
)) {
749 WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit
, __func__
);
753 bcopy(&wl
->pub
->cur_etheraddr
, perm
, ETH_ALEN
);
754 ASSERT(is_valid_ether_addr(perm
));
755 SET_IEEE80211_PERM_ADDR(hw
, perm
);
757 err
= ieee80211_register_hw(hw
);
759 WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
763 if (wl
->pub
->srom_ccode
[0])
764 err
= wl_set_hint(wl
, wl
->pub
->srom_ccode
);
766 err
= wl_set_hint(wl
, "US");
768 WL_ERROR("%s: regulatory_hint failed, status %d\n",
771 WL_ERROR("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver (" PHY_VERSION_STR
")",
775 printf(" (Compiled at " __TIME__
" on " __DATE__
")");
790 #define CHAN2GHZ(channel, freqency, chflags) { \
791 .band = IEEE80211_BAND_2GHZ, \
792 .center_freq = (freqency), \
793 .hw_value = (channel), \
795 .max_antenna_gain = 0, \
799 static struct ieee80211_channel wl_2ghz_chantable
[] = {
800 CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS
),
801 CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS
),
802 CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS
),
803 CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS
),
804 CHAN2GHZ(5, 2432, 0),
805 CHAN2GHZ(6, 2437, 0),
806 CHAN2GHZ(7, 2442, 0),
807 CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS
),
808 CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS
),
809 CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS
),
810 CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS
),
812 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_IBSS
|
813 IEEE80211_CHAN_NO_HT40PLUS
),
815 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_IBSS
|
816 IEEE80211_CHAN_NO_HT40PLUS
),
818 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_IBSS
|
819 IEEE80211_CHAN_NO_HT40PLUS
| IEEE80211_CHAN_NO_HT40MINUS
)
822 #define CHAN5GHZ(channel, chflags) { \
823 .band = IEEE80211_BAND_5GHZ, \
824 .center_freq = 5000 + 5*(channel), \
825 .hw_value = (channel), \
827 .max_antenna_gain = 0, \
831 static struct ieee80211_channel wl_5ghz_nphy_chantable
[] = {
833 CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS
),
834 CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS
),
835 CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS
),
836 CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS
),
839 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
840 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
842 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
843 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
845 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
846 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
848 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
849 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
852 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
853 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
855 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
856 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
858 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
859 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
861 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
862 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
864 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
865 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
867 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
868 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
870 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
871 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
873 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
874 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
876 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
877 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40MINUS
),
879 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
880 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
),
882 IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IBSS
|
883 IEEE80211_CHAN_PASSIVE_SCAN
| IEEE80211_CHAN_NO_HT40PLUS
|
884 IEEE80211_CHAN_NO_HT40MINUS
),
886 CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS
),
887 CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS
),
888 CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS
),
889 CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS
),
890 CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS
| IEEE80211_CHAN_NO_HT40MINUS
)
893 #define RATE(rate100m, _flags) { \
894 .bitrate = (rate100m), \
896 .hw_value = (rate100m / 5), \
899 static struct ieee80211_rate wl_legacy_ratetable
[] = {
901 RATE(20, IEEE80211_RATE_SHORT_PREAMBLE
),
902 RATE(55, IEEE80211_RATE_SHORT_PREAMBLE
),
903 RATE(110, IEEE80211_RATE_SHORT_PREAMBLE
),
914 static struct ieee80211_supported_band wl_band_2GHz_nphy
= {
915 .band
= IEEE80211_BAND_2GHZ
,
916 .channels
= wl_2ghz_chantable
,
917 .n_channels
= ARRAY_SIZE(wl_2ghz_chantable
),
918 .bitrates
= wl_legacy_ratetable
,
919 .n_bitrates
= ARRAY_SIZE(wl_legacy_ratetable
),
921 /* from include/linux/ieee80211.h */
922 .cap
= IEEE80211_HT_CAP_GRN_FLD
|
923 IEEE80211_HT_CAP_SGI_20
|
924 IEEE80211_HT_CAP_SGI_40
| IEEE80211_HT_CAP_40MHZ_INTOLERANT
,
925 .ht_supported
= true,
926 .ampdu_factor
= AMPDU_RX_FACTOR_64K
,
927 .ampdu_density
= AMPDU_DEF_MPDU_DENSITY
,
929 /* placeholders for now */
930 .rx_mask
= {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
932 .tx_params
= IEEE80211_HT_MCS_TX_DEFINED
}
936 static struct ieee80211_supported_band wl_band_5GHz_nphy
= {
937 .band
= IEEE80211_BAND_5GHZ
,
938 .channels
= wl_5ghz_nphy_chantable
,
939 .n_channels
= ARRAY_SIZE(wl_5ghz_nphy_chantable
),
940 .bitrates
= wl_legacy_ratetable
+ 4,
941 .n_bitrates
= ARRAY_SIZE(wl_legacy_ratetable
) - 4,
943 /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
944 .cap
= IEEE80211_HT_CAP_GRN_FLD
| IEEE80211_HT_CAP_SGI_20
| IEEE80211_HT_CAP_SGI_40
| IEEE80211_HT_CAP_40MHZ_INTOLERANT
, /* No 40 mhz yet */
945 .ht_supported
= true,
946 .ampdu_factor
= AMPDU_RX_FACTOR_64K
,
947 .ampdu_density
= AMPDU_DEF_MPDU_DENSITY
,
949 /* placeholders for now */
950 .rx_mask
= {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
952 .tx_params
= IEEE80211_HT_MCS_TX_DEFINED
}
956 static int ieee_hw_rate_init(struct ieee80211_hw
*hw
)
958 struct wl_info
*wl
= HW_TO_WL(hw
);
964 hw
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = NULL
;
965 hw
->wiphy
->bands
[IEEE80211_BAND_5GHZ
] = NULL
;
967 if (wlc_get(wl
->wlc
, WLC_GET_PHYLIST
, (int *)&phy_list
) < 0) {
968 WL_ERROR("Phy list failed\n");
970 WL_NONE("%s: phylist = %c\n", __func__
, phy_list
[0]);
972 if (phy_list
[0] == 'n' || phy_list
[0] == 'c') {
973 if (phy_list
[0] == 'c') {
975 wl_band_2GHz_nphy
.ht_cap
.mcs
.rx_mask
[1] = 0;
976 wl_band_2GHz_nphy
.ht_cap
.mcs
.rx_highest
= 72;
978 hw
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &wl_band_2GHz_nphy
;
984 /* Assume all bands use the same phy. True for 11n devices. */
985 if (NBANDS_PUB(wl
->pub
) > 1) {
987 if (phy_list
[0] == 'n' || phy_list
[0] == 'c') {
988 hw
->wiphy
->bands
[IEEE80211_BAND_5GHZ
] =
995 WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__
, 1, has_5g
);
1000 static int ieee_hw_init(struct ieee80211_hw
*hw
)
1002 hw
->flags
= IEEE80211_HW_SIGNAL_DBM
1003 /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */
1004 | IEEE80211_HW_REPORTS_TX_ACK_STATUS
1005 | IEEE80211_HW_AMPDU_AGGREGATION
;
1007 hw
->extra_tx_headroom
= wlc_get_header_len();
1008 /* FIXME: should get this from wlc->machwcap */
1010 /* FIXME: this doesn't seem to be used properly in minstrel_ht.
1011 * mac80211/status.c:ieee80211_tx_status() checks this value,
1012 * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
1013 * appears to always set 3 rates
1015 hw
->max_rates
= 2; /* Primary rate and 1 fallback rate */
1017 hw
->channel_change_time
= 7 * 1000; /* channel change time is dependant on chip and band */
1018 hw
->wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
);
1020 hw
->rate_control_algorithm
= "minstrel_ht";
1022 hw
->sta_data_size
= sizeof(struct scb
);
1023 return ieee_hw_rate_init(hw
);
1027 * determines if a device is a WL device, and if so, attaches it.
1029 * This function determines if a device pointed to by pdev is a WL device,
1030 * and if so, performs a wl_attach() on it.
1034 wl_pci_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
1038 struct ieee80211_hw
*hw
;
1043 WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
1044 __func__
, pdev
->bus
->number
, PCI_SLOT(pdev
->devfn
),
1045 PCI_FUNC(pdev
->devfn
), pdev
->irq
);
1047 if ((pdev
->vendor
!= PCI_VENDOR_ID_BROADCOM
) ||
1048 (((pdev
->device
& 0xff00) != 0x4300) &&
1049 ((pdev
->device
& 0xff00) != 0x4700) &&
1050 ((pdev
->device
< 43000) || (pdev
->device
> 43999))))
1053 rc
= pci_enable_device(pdev
);
1055 WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
1056 __func__
, pdev
->bus
->number
, PCI_SLOT(pdev
->devfn
),
1057 PCI_FUNC(pdev
->devfn
));
1060 pci_set_master(pdev
);
1062 pci_read_config_dword(pdev
, 0x40, &val
);
1063 if ((val
& 0x0000ff00) != 0)
1064 pci_write_config_dword(pdev
, 0x40, val
& 0xffff00ff);
1066 hw
= ieee80211_alloc_hw(sizeof(struct wl_info
), &wl_ops
);
1068 WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__
);
1073 SET_IEEE80211_DEV(hw
, &pdev
->dev
);
1075 pci_set_drvdata(pdev
, hw
);
1077 memset(hw
->priv
, 0, sizeof(*wl
));
1079 wl
= wl_attach(pdev
->vendor
, pdev
->device
, pci_resource_start(pdev
, 0),
1080 PCI_BUS
, pdev
, pdev
->irq
);
1083 WL_ERROR("%s: %s: wl_attach failed!\n",
1084 KBUILD_MODNAME
, __func__
);
1089 WL_ERROR("%s: err_1: Major hoarkage\n", __func__
);
1094 static int wl_suspend(struct pci_dev
*pdev
, pm_message_t state
)
1097 struct ieee80211_hw
*hw
;
1099 WL_TRACE("wl: wl_suspend\n");
1101 hw
= pci_get_drvdata(pdev
);
1104 WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
1110 wl
->pub
->hw_up
= false;
1112 pci_save_state(pdev
, wl
->pci_psstate
);
1113 pci_disable_device(pdev
);
1114 return pci_set_power_state(pdev
, PCI_D3hot
);
1117 static int wl_resume(struct pci_dev
*pdev
)
1120 struct ieee80211_hw
*hw
;
1124 WL_TRACE("wl: wl_resume\n");
1125 hw
= pci_get_drvdata(pdev
);
1128 WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
1132 err
= pci_set_power_state(pdev
, PCI_D0
);
1136 pci_restore_state(pdev
, wl
->pci_psstate
);
1138 err
= pci_enable_device(pdev
);
1142 pci_set_master(pdev
);
1144 pci_read_config_dword(pdev
, 0x40, &val
);
1145 if ((val
& 0x0000ff00) != 0)
1146 pci_write_config_dword(pdev
, 0x40, val
& 0xffff00ff);
1154 #endif /* LINUXSTA_PS */
1156 static void wl_remove(struct pci_dev
*pdev
)
1159 struct ieee80211_hw
*hw
;
1161 hw
= pci_get_drvdata(pdev
);
1164 WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
1167 if (!wlc_chipmatch(pdev
->vendor
, pdev
->device
)) {
1168 WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
1172 ieee80211_unregister_hw(hw
);
1176 WL_NONE("%s: Down\n", __func__
);
1178 pci_disable_device(pdev
);
1182 pci_set_drvdata(pdev
, NULL
);
1183 ieee80211_free_hw(hw
);
1186 static struct pci_driver wl_pci_driver
= {
1187 .name
= "brcm80211",
1188 .probe
= wl_pci_probe
,
1190 .suspend
= wl_suspend
,
1191 .resume
= wl_resume
,
1192 #endif /* LINUXSTA_PS */
1193 .remove
= __devexit_p(wl_remove
),
1194 .id_table
= wl_id_table
,
1198 * This is the main entry point for the WL driver.
1200 * This function determines if a device pointed to by pdev is a WL device,
1201 * and if so, performs a wl_attach() on it.
1204 static int __init
wl_module_init(void)
1206 int error
= -ENODEV
;
1209 if (msglevel
!= 0xdeadbeef)
1210 wl_msg_level
= msglevel
;
1212 char *var
= getvar(NULL
, "wl_msglevel");
1214 wl_msg_level
= simple_strtoul(var
, NULL
, 0);
1217 extern u32 phyhal_msg_level
;
1219 if (phymsglevel
!= 0xdeadbeef)
1220 phyhal_msg_level
= phymsglevel
;
1222 char *var
= getvar(NULL
, "phy_msglevel");
1224 phyhal_msg_level
= simple_strtoul(var
, NULL
, 0);
1229 error
= pci_register_driver(&wl_pci_driver
);
1239 * This function unloads the WL driver from the system.
1241 * This function unconditionally unloads the WL driver module from the
1245 static void __exit
wl_module_exit(void)
1247 pci_unregister_driver(&wl_pci_driver
);
1251 module_init(wl_module_init
);
1252 module_exit(wl_module_exit
);
1255 * This function frees the WL per-device resources.
1257 * This function frees resources owned by the WL device pointed to
1258 * by the wl parameter.
1261 void wl_free(struct wl_info
*wl
)
1263 wl_timer_t
*t
, *next
;
1264 struct osl_info
*osh
;
1267 /* free ucode data */
1269 wl_ucode_data_free();
1271 free_irq(wl
->irq
, wl
);
1274 tasklet_kill(&wl
->tasklet
);
1277 wlc_module_unregister(wl
->pub
, "linux", wl
);
1280 /* free common resources */
1282 wlc_detach(wl
->wlc
);
1287 /* virtual interface deletion is deferred so we cannot spinwait */
1289 /* wait for all pending callbacks to complete */
1290 while (atomic_read(&wl
->callbacks
) > 0)
1294 for (t
= wl
->timers
; t
; t
= next
) {
1306 * unregister_netdev() calls get_stats() which may read chip registers
1307 * so we cannot unmap the chip registers until after calling unregister_netdev() .
1309 if (wl
->regsva
&& wl
->bcm_bustype
!= SDIO_BUS
&&
1310 wl
->bcm_bustype
!= JTAG_BUS
) {
1311 iounmap((void *)wl
->regsva
);
1319 /* transmit a packet */
1320 static int BCMFASTPATH
wl_start(struct sk_buff
*skb
, struct wl_info
*wl
)
1325 return wl_start_int(wl
, WL_TO_HW(wl
), skb
);
1328 static int BCMFASTPATH
1329 wl_start_int(struct wl_info
*wl
, struct ieee80211_hw
*hw
, struct sk_buff
*skb
)
1331 wlc_sendpkt_mac80211(wl
->wlc
, skb
, hw
);
1332 return NETDEV_TX_OK
;
1335 void wl_txflowcontrol(struct wl_info
*wl
, struct wl_if
*wlif
, bool state
,
1338 WL_ERROR("Shouldn't be here %s\n", __func__
);
1341 void wl_init(struct wl_info
*wl
)
1343 WL_TRACE("wl%d: wl_init\n", wl
->pub
->unit
);
1350 uint
wl_reset(struct wl_info
*wl
)
1352 WL_TRACE("wl%d: wl_reset\n", wl
->pub
->unit
);
1356 /* dpc will not be rescheduled */
1363 * These are interrupt on/off entry points. Disable interrupts
1364 * during interrupt state transition.
1366 void BCMFASTPATH
wl_intrson(struct wl_info
*wl
)
1368 unsigned long flags
;
1370 INT_LOCK(wl
, flags
);
1371 wlc_intrson(wl
->wlc
);
1372 INT_UNLOCK(wl
, flags
);
1375 bool wl_alloc_dma_resources(struct wl_info
*wl
, uint addrwidth
)
1380 u32 BCMFASTPATH
wl_intrsoff(struct wl_info
*wl
)
1382 unsigned long flags
;
1385 INT_LOCK(wl
, flags
);
1386 status
= wlc_intrsoff(wl
->wlc
);
1387 INT_UNLOCK(wl
, flags
);
1391 void wl_intrsrestore(struct wl_info
*wl
, u32 macintmask
)
1393 unsigned long flags
;
1395 INT_LOCK(wl
, flags
);
1396 wlc_intrsrestore(wl
->wlc
, macintmask
);
1397 INT_UNLOCK(wl
, flags
);
1400 int wl_up(struct wl_info
*wl
)
1407 error
= wlc_up(wl
->wlc
);
1412 void wl_down(struct wl_info
*wl
)
1414 uint callbacks
, ret_val
= 0;
1416 /* call common down function */
1417 ret_val
= wlc_down(wl
->wlc
);
1418 callbacks
= atomic_read(&wl
->callbacks
) - ret_val
;
1420 /* wait for down callbacks to complete */
1423 /* For HIGH_only driver, it's important to actually schedule other work,
1424 * not just spin wait since everything runs at schedule level
1426 SPINWAIT((atomic_read(&wl
->callbacks
) > callbacks
), 100 * 1000);
1431 irqreturn_t BCMFASTPATH
wl_isr(int irq
, void *dev_id
)
1435 unsigned long flags
;
1437 wl
= (struct wl_info
*) dev_id
;
1439 WL_ISRLOCK(wl
, flags
);
1441 /* call common first level interrupt handler */
1442 ours
= wlc_isr(wl
->wlc
, &wantdpc
);
1444 /* if more to do... */
1447 /* ...and call the second level interrupt handler */
1449 ASSERT(wl
->resched
== false);
1450 tasklet_schedule(&wl
->tasklet
);
1454 WL_ISRUNLOCK(wl
, flags
);
1456 return IRQ_RETVAL(ours
);
1459 static void BCMFASTPATH
wl_dpc(unsigned long data
)
1463 wl
= (struct wl_info
*) data
;
1467 /* call the common second level interrupt handler */
1470 unsigned long flags
;
1472 INT_LOCK(wl
, flags
);
1473 wlc_intrsupd(wl
->wlc
);
1474 INT_UNLOCK(wl
, flags
);
1477 wl
->resched
= wlc_dpc(wl
->wlc
, true);
1480 /* wlc_dpc() may bring the driver down */
1484 /* re-schedule dpc */
1486 tasklet_schedule(&wl
->tasklet
);
1488 /* re-enable interrupts */
1496 static void wl_link_up(struct wl_info
*wl
, char *ifname
)
1498 WL_ERROR("wl%d: link up (%s)\n", wl
->pub
->unit
, ifname
);
1501 static void wl_link_down(struct wl_info
*wl
, char *ifname
)
1503 WL_ERROR("wl%d: link down (%s)\n", wl
->pub
->unit
, ifname
);
1506 void wl_event(struct wl_info
*wl
, char *ifname
, wlc_event_t
*e
)
1509 switch (e
->event
.event_type
) {
1511 case WLC_E_NDIS_LINK
:
1512 if (e
->event
.flags
& WLC_EVENT_MSG_LINK
)
1513 wl_link_up(wl
, ifname
);
1515 wl_link_down(wl
, ifname
);
1522 static void wl_timer(unsigned long data
)
1524 _wl_timer((wl_timer_t
*) data
);
1527 static void _wl_timer(wl_timer_t
*t
)
1533 t
->timer
.expires
= jiffies
+ t
->ms
* HZ
/ 1000;
1534 atomic_inc(&t
->wl
->callbacks
);
1535 add_timer(&t
->timer
);
1543 atomic_dec(&t
->wl
->callbacks
);
1548 wl_timer_t
*wl_init_timer(struct wl_info
*wl
, void (*fn
) (void *arg
), void *arg
,
1553 t
= kmalloc(sizeof(wl_timer_t
), GFP_ATOMIC
);
1555 WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl
->pub
->unit
);
1559 memset(t
, 0, sizeof(wl_timer_t
));
1561 init_timer(&t
->timer
);
1562 t
->timer
.data
= (unsigned long) t
;
1563 t
->timer
.function
= wl_timer
;
1567 t
->next
= wl
->timers
;
1571 t
->name
= kmalloc(strlen(name
) + 1, GFP_ATOMIC
);
1573 strcpy(t
->name
, name
);
1579 /* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
1580 * as well as it's easier to make it periodic
1582 void wl_add_timer(struct wl_info
*wl
, wl_timer_t
*t
, uint ms
, int periodic
)
1586 WL_ERROR("%s: Already set. Name: %s, per %d\n",
1587 __func__
, t
->name
, periodic
);
1593 t
->periodic
= (bool) periodic
;
1595 t
->timer
.expires
= jiffies
+ ms
* HZ
/ 1000;
1597 atomic_inc(&wl
->callbacks
);
1598 add_timer(&t
->timer
);
1601 /* return true if timer successfully deleted, false if still pending */
1602 bool wl_del_timer(struct wl_info
*wl
, wl_timer_t
*t
)
1606 if (!del_timer(&t
->timer
)) {
1609 atomic_dec(&wl
->callbacks
);
1615 void wl_free_timer(struct wl_info
*wl
, wl_timer_t
*t
)
1619 /* delete the timer in case it is active */
1620 wl_del_timer(wl
, t
);
1622 if (wl
->timers
== t
) {
1623 wl
->timers
= wl
->timers
->next
;
1635 if (tmp
->next
== t
) {
1636 tmp
->next
= t
->next
;
1649 static int wl_linux_watchdog(void *ctx
)
1651 struct wl_info
*wl
= (struct wl_info
*) ctx
;
1652 struct net_device_stats
*stats
= NULL
;
1656 ASSERT(wl
->stats_id
< 2);
1658 id
= 1 - wl
->stats_id
;
1660 stats
= &wl
->stats_watchdog
[id
];
1661 stats
->rx_packets
= WLCNTVAL(wl
->pub
->_cnt
->rxframe
);
1662 stats
->tx_packets
= WLCNTVAL(wl
->pub
->_cnt
->txframe
);
1663 stats
->rx_bytes
= WLCNTVAL(wl
->pub
->_cnt
->rxbyte
);
1664 stats
->tx_bytes
= WLCNTVAL(wl
->pub
->_cnt
->txbyte
);
1665 stats
->rx_errors
= WLCNTVAL(wl
->pub
->_cnt
->rxerror
);
1666 stats
->tx_errors
= WLCNTVAL(wl
->pub
->_cnt
->txerror
);
1667 stats
->collisions
= 0;
1669 stats
->rx_length_errors
= 0;
1670 stats
->rx_over_errors
= WLCNTVAL(wl
->pub
->_cnt
->rxoflo
);
1671 stats
->rx_crc_errors
= WLCNTVAL(wl
->pub
->_cnt
->rxcrc
);
1672 stats
->rx_frame_errors
= 0;
1673 stats
->rx_fifo_errors
= WLCNTVAL(wl
->pub
->_cnt
->rxoflo
);
1674 stats
->rx_missed_errors
= 0;
1676 stats
->tx_fifo_errors
= WLCNTVAL(wl
->pub
->_cnt
->txuflo
);
1691 char *wl_firmwares
[WL_MAX_FW
] = {
1696 int wl_ucode_init_buf(struct wl_info
*wl
, void **pbuf
, u32 idx
)
1700 struct wl_fw_hdr
*hdr
;
1701 for (i
= 0; i
< wl
->fw
.fw_cnt
; i
++) {
1702 hdr
= (struct wl_fw_hdr
*)wl
->fw
.fw_hdr
[i
]->data
;
1703 for (entry
= 0; entry
< wl
->fw
.hdr_num_entries
[i
];
1705 if (hdr
->idx
== idx
) {
1706 pdata
= wl
->fw
.fw_bin
[i
]->data
+ hdr
->offset
;
1707 *pbuf
= kmalloc(hdr
->len
, GFP_ATOMIC
);
1708 if (*pbuf
== NULL
) {
1709 printf("fail to alloc %d bytes\n",
1712 bcopy(pdata
, *pbuf
, hdr
->len
);
1717 printf("ERROR: ucode buf tag:%d can not be found!\n", idx
);
1722 int wl_ucode_init_uint(struct wl_info
*wl
, u32
*data
, u32 idx
)
1726 struct wl_fw_hdr
*hdr
;
1727 for (i
= 0; i
< wl
->fw
.fw_cnt
; i
++) {
1728 hdr
= (struct wl_fw_hdr
*)wl
->fw
.fw_hdr
[i
]->data
;
1729 for (entry
= 0; entry
< wl
->fw
.hdr_num_entries
[i
];
1731 if (hdr
->idx
== idx
) {
1732 pdata
= wl
->fw
.fw_bin
[i
]->data
+ hdr
->offset
;
1733 ASSERT(hdr
->len
== 4);
1734 *data
= *((u32
*) pdata
);
1739 printf("ERROR: ucode tag:%d can not be found!\n", idx
);
1743 static int wl_request_fw(struct wl_info
*wl
, struct pci_dev
*pdev
)
1746 struct device
*device
= &pdev
->dev
;
1750 memset((void *)&wl
->fw
, 0, sizeof(struct wl_firmware
));
1751 for (i
= 0; i
< WL_MAX_FW
; i
++) {
1752 if (wl_firmwares
[i
] == NULL
)
1754 sprintf(fw_name
, "%s-%d.fw", wl_firmwares
[i
],
1755 UCODE_LOADER_API_VER
);
1756 WL_NONE("request fw %s\n", fw_name
);
1757 status
= request_firmware(&wl
->fw
.fw_bin
[i
], fw_name
, device
);
1759 printf("%s: fail to load firmware %s\n",
1760 KBUILD_MODNAME
, fw_name
);
1764 WL_NONE("request fw %s\n", fw_name
);
1765 sprintf(fw_name
, "%s_hdr-%d.fw", wl_firmwares
[i
],
1766 UCODE_LOADER_API_VER
);
1767 status
= request_firmware(&wl
->fw
.fw_hdr
[i
], fw_name
, device
);
1769 printf("%s: fail to load firmware %s\n",
1770 KBUILD_MODNAME
, fw_name
);
1774 wl
->fw
.hdr_num_entries
[i
] =
1775 wl
->fw
.fw_hdr
[i
]->size
/ (sizeof(struct wl_fw_hdr
));
1776 WL_NONE("request fw %s find: %d entries\n",
1777 fw_name
, wl
->fw
.hdr_num_entries
[i
]);
1780 return wl_ucode_data_init(wl
);
1783 void wl_ucode_free_buf(void *p
)
1788 static void wl_release_fw(struct wl_info
*wl
)
1791 for (i
= 0; i
< WL_MAX_FW
; i
++) {
1792 release_firmware(wl
->fw
.fw_bin
[i
]);
1793 release_firmware(wl
->fw
.fw_hdr
[i
]);
1799 * checks validity of all firmware images loaded from user space
1801 int wl_check_firmwares(struct wl_info
*wl
)
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
) {
1814 } else if (fw
== NULL
|| fw_hdr
== NULL
) {
1815 WL_ERROR("%s: invalid bin/hdr fw\n", __func__
);
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
));
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
);
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
>
1833 WL_ERROR("%s: conflicting bin/hdr\n",
1840 if (rc
== 0 && wl
->fw
.fw_cnt
!= i
) {
1841 WL_ERROR("%s: invalid fw_cnt=%d\n", __func__
, wl
->fw
.fw_cnt
);