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 #include <linux/kernel.h>
18 #include <linux/etherdevice.h>
19 #include <linux/module.h>
20 #include <net/cfg80211.h>
21 #include <net/rtnetlink.h>
22 #include <brcmu_utils.h>
23 #include <brcmu_wifi.h>
27 #include "dhd_proto.h"
29 #include "wl_cfg80211.h"
32 MODULE_AUTHOR("Broadcom Corporation");
33 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
34 MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
35 MODULE_LICENSE("Dual BSD/GPL");
37 #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */
41 module_param(brcmf_msg_level
, int, 0);
44 char *brcmf_ifname(struct brcmf_pub
*drvr
, int ifidx
)
46 if (ifidx
< 0 || ifidx
>= BRCMF_MAX_IFS
) {
47 brcmf_err("ifidx %d out of range\n", ifidx
);
51 if (drvr
->iflist
[ifidx
] == NULL
) {
52 brcmf_err("null i/f %d\n", ifidx
);
56 if (drvr
->iflist
[ifidx
]->ndev
)
57 return drvr
->iflist
[ifidx
]->ndev
->name
;
62 static void _brcmf_set_multicast_list(struct work_struct
*work
)
65 struct net_device
*ndev
;
66 struct netdev_hw_addr
*ha
;
73 brcmf_dbg(TRACE
, "enter\n");
75 ifp
= container_of(work
, struct brcmf_if
, multicast_work
);
78 /* Determine initial value of allmulti flag */
79 cmd_value
= (ndev
->flags
& IFF_ALLMULTI
) ? true : false;
81 /* Send down the multicast list first. */
82 cnt
= netdev_mc_count(ndev
);
83 buflen
= sizeof(cnt
) + (cnt
* ETH_ALEN
);
84 buf
= kmalloc(buflen
, GFP_ATOMIC
);
89 cnt_le
= cpu_to_le32(cnt
);
90 memcpy(bufp
, &cnt_le
, sizeof(cnt_le
));
91 bufp
+= sizeof(cnt_le
);
93 netdev_for_each_mc_addr(ha
, ndev
) {
96 memcpy(bufp
, ha
->addr
, ETH_ALEN
);
101 err
= brcmf_fil_iovar_data_set(ifp
, "mcast_list", buf
, buflen
);
103 brcmf_err("Setting mcast_list failed, %d\n", err
);
104 cmd_value
= cnt
? true : cmd_value
;
110 * Now send the allmulti setting. This is based on the setting in the
111 * net_device flags, but might be modified above to be turned on if we
112 * were trying to set some addresses and dongle rejected it...
114 err
= brcmf_fil_iovar_int_set(ifp
, "allmulti", cmd_value
);
116 brcmf_err("Setting allmulti failed, %d\n", err
);
118 /*Finally, pick up the PROMISC flag */
119 cmd_value
= (ndev
->flags
& IFF_PROMISC
) ? true : false;
120 err
= brcmf_fil_cmd_int_set(ifp
, BRCMF_C_SET_PROMISC
, cmd_value
);
122 brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
127 _brcmf_set_mac_address(struct work_struct
*work
)
129 struct brcmf_if
*ifp
;
132 brcmf_dbg(TRACE
, "enter\n");
134 ifp
= container_of(work
, struct brcmf_if
, setmacaddr_work
);
135 err
= brcmf_fil_iovar_data_set(ifp
, "cur_etheraddr", ifp
->mac_addr
,
138 brcmf_err("Setting cur_etheraddr failed, %d\n", err
);
140 brcmf_dbg(TRACE
, "MAC address updated to %pM\n",
142 memcpy(ifp
->ndev
->dev_addr
, ifp
->mac_addr
, ETH_ALEN
);
146 static int brcmf_netdev_set_mac_address(struct net_device
*ndev
, void *addr
)
148 struct brcmf_if
*ifp
= netdev_priv(ndev
);
149 struct sockaddr
*sa
= (struct sockaddr
*)addr
;
151 memcpy(&ifp
->mac_addr
, sa
->sa_data
, ETH_ALEN
);
152 schedule_work(&ifp
->setmacaddr_work
);
156 static void brcmf_netdev_set_multicast_list(struct net_device
*ndev
)
158 struct brcmf_if
*ifp
= netdev_priv(ndev
);
160 schedule_work(&ifp
->multicast_work
);
163 static int brcmf_netdev_start_xmit(struct sk_buff
*skb
, struct net_device
*ndev
)
166 struct brcmf_if
*ifp
= netdev_priv(ndev
);
167 struct brcmf_pub
*drvr
= ifp
->drvr
;
170 brcmf_dbg(TRACE
, "Enter\n");
173 if (!drvr
->bus_if
->drvr_up
||
174 (drvr
->bus_if
->state
!= BRCMF_BUS_DATA
)) {
175 brcmf_err("xmit rejected drvup=%d state=%d\n",
176 drvr
->bus_if
->drvr_up
,
177 drvr
->bus_if
->state
);
178 netif_stop_queue(ndev
);
182 if (!drvr
->iflist
[ifp
->idx
]) {
183 brcmf_err("bad ifidx %d\n", ifp
->idx
);
184 netif_stop_queue(ndev
);
188 /* Make sure there's enough room for any header */
189 if (skb_headroom(skb
) < drvr
->hdrlen
) {
190 struct sk_buff
*skb2
;
192 brcmf_dbg(INFO
, "%s: insufficient headroom\n",
193 brcmf_ifname(drvr
, ifp
->idx
));
194 drvr
->bus_if
->tx_realloc
++;
195 skb2
= skb_realloc_headroom(skb
, drvr
->hdrlen
);
199 brcmf_err("%s: skb_realloc_headroom failed\n",
200 brcmf_ifname(drvr
, ifp
->idx
));
206 /* validate length for ether packet */
207 if (skb
->len
< sizeof(*eh
)) {
213 /* handle ethernet header */
214 eh
= (struct ethhdr
*)(skb
->data
);
215 if (is_multicast_ether_addr(eh
->h_dest
))
216 drvr
->tx_multicast
++;
217 if (ntohs(eh
->h_proto
) == ETH_P_PAE
)
218 atomic_inc(&drvr
->pend_8021x_cnt
);
220 /* If the protocol uses a data header, apply it */
221 brcmf_proto_hdrpush(drvr
, ifp
->idx
, skb
);
223 /* Use bus module to send data frame */
224 ret
= brcmf_bus_txdata(drvr
->bus_if
, skb
);
228 drvr
->bus_if
->dstats
.tx_dropped
++;
230 drvr
->bus_if
->dstats
.tx_packets
++;
232 /* Return ok: we always eat the packet */
236 void brcmf_txflowblock(struct device
*dev
, bool state
)
238 struct net_device
*ndev
;
239 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
240 struct brcmf_pub
*drvr
= bus_if
->drvr
;
243 brcmf_dbg(TRACE
, "Enter\n");
245 for (i
= 0; i
< BRCMF_MAX_IFS
; i
++)
246 if (drvr
->iflist
[i
]) {
247 ndev
= drvr
->iflist
[i
]->ndev
;
249 netif_stop_queue(ndev
);
251 netif_wake_queue(ndev
);
255 void brcmf_rx_frames(struct device
*dev
, struct sk_buff_head
*skb_list
)
259 struct sk_buff
*skb
, *pnext
;
260 struct brcmf_if
*ifp
;
261 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
262 struct brcmf_pub
*drvr
= bus_if
->drvr
;
266 brcmf_dbg(TRACE
, "Enter\n");
268 skb_queue_walk_safe(skb_list
, skb
, pnext
) {
269 skb_unlink(skb
, skb_list
);
271 /* process and remove protocol-specific header
273 ret
= brcmf_proto_hdrpull(drvr
, &ifidx
, skb
);
276 bus_if
->dstats
.rx_errors
++;
277 brcmu_pkt_buf_free_skb(skb
);
281 /* Get the protocol, maintain skb around eth_type_trans()
282 * The main reason for this hack is for the limitation of
283 * Linux 2.4 where 'eth_type_trans' uses the
284 * 'net->hard_header_len'
285 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
286 * coping of the packet coming from the network stack to add
287 * BDC, Hardware header etc, during network interface
289 * we set the 'net->hard_header_len' to ETH_HLEN + extra space
291 * for BDC, Hardware header etc. and not just the ETH_HLEN
296 ifp
= drvr
->iflist
[ifidx
];
298 ifp
= drvr
->iflist
[0];
300 if (!ifp
|| !ifp
->ndev
||
301 ifp
->ndev
->reg_state
!= NETREG_REGISTERED
) {
302 brcmu_pkt_buf_free_skb(skb
);
306 skb
->dev
= ifp
->ndev
;
307 skb
->protocol
= eth_type_trans(skb
, skb
->dev
);
309 if (skb
->pkt_type
== PACKET_MULTICAST
)
310 bus_if
->dstats
.multicast
++;
315 /* Strip header, count, deliver upward */
316 skb_pull(skb
, ETH_HLEN
);
318 /* Process special event packets and then discard them */
319 brcmf_fweh_process_skb(drvr
, skb
, &ifidx
);
321 if (drvr
->iflist
[ifidx
]) {
322 ifp
= drvr
->iflist
[ifidx
];
323 ifp
->ndev
->last_rx
= jiffies
;
326 bus_if
->dstats
.rx_bytes
+= skb
->len
;
327 bus_if
->dstats
.rx_packets
++; /* Local count */
332 /* If the receive is not processed inside an ISR,
333 * the softirqd must be woken explicitly to service
334 * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
335 * by netif_rx_ni(), but in earlier kernels, we need
342 void brcmf_txcomplete(struct device
*dev
, struct sk_buff
*txp
, bool success
)
347 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
348 struct brcmf_pub
*drvr
= bus_if
->drvr
;
350 brcmf_proto_hdrpull(drvr
, &ifidx
, txp
);
352 eh
= (struct ethhdr
*)(txp
->data
);
353 type
= ntohs(eh
->h_proto
);
355 if (type
== ETH_P_PAE
) {
356 atomic_dec(&drvr
->pend_8021x_cnt
);
357 if (waitqueue_active(&drvr
->pend_8021x_wait
))
358 wake_up(&drvr
->pend_8021x_wait
);
362 static struct net_device_stats
*brcmf_netdev_get_stats(struct net_device
*ndev
)
364 struct brcmf_if
*ifp
= netdev_priv(ndev
);
365 struct brcmf_bus
*bus_if
= ifp
->drvr
->bus_if
;
367 brcmf_dbg(TRACE
, "Enter\n");
369 /* Copy dongle stats to net device stats */
370 ifp
->stats
.rx_packets
= bus_if
->dstats
.rx_packets
;
371 ifp
->stats
.tx_packets
= bus_if
->dstats
.tx_packets
;
372 ifp
->stats
.rx_bytes
= bus_if
->dstats
.rx_bytes
;
373 ifp
->stats
.tx_bytes
= bus_if
->dstats
.tx_bytes
;
374 ifp
->stats
.rx_errors
= bus_if
->dstats
.rx_errors
;
375 ifp
->stats
.tx_errors
= bus_if
->dstats
.tx_errors
;
376 ifp
->stats
.rx_dropped
= bus_if
->dstats
.rx_dropped
;
377 ifp
->stats
.tx_dropped
= bus_if
->dstats
.tx_dropped
;
378 ifp
->stats
.multicast
= bus_if
->dstats
.multicast
;
384 * Set current toe component enables in toe_ol iovar,
385 * and set toe global enable iovar
387 static int brcmf_toe_set(struct brcmf_if
*ifp
, u32 toe_ol
)
391 err
= brcmf_fil_iovar_int_set(ifp
, "toe_ol", toe_ol
);
393 brcmf_err("Setting toe_ol failed, %d\n", err
);
397 err
= brcmf_fil_iovar_int_set(ifp
, "toe", (toe_ol
!= 0));
399 brcmf_err("Setting toe failed, %d\n", err
);
405 static void brcmf_ethtool_get_drvinfo(struct net_device
*ndev
,
406 struct ethtool_drvinfo
*info
)
408 struct brcmf_if
*ifp
= netdev_priv(ndev
);
409 struct brcmf_pub
*drvr
= ifp
->drvr
;
411 sprintf(info
->driver
, KBUILD_MODNAME
);
412 sprintf(info
->version
, "%lu", drvr
->drv_version
);
413 sprintf(info
->bus_info
, "%s", dev_name(drvr
->bus_if
->dev
));
416 static const struct ethtool_ops brcmf_ethtool_ops
= {
417 .get_drvinfo
= brcmf_ethtool_get_drvinfo
,
420 static int brcmf_ethtool(struct brcmf_if
*ifp
, void __user
*uaddr
)
422 struct brcmf_pub
*drvr
= ifp
->drvr
;
423 struct ethtool_drvinfo info
;
424 char drvname
[sizeof(info
.driver
)];
426 struct ethtool_value edata
;
427 u32 toe_cmpnt
, csum_dir
;
430 brcmf_dbg(TRACE
, "Enter\n");
432 /* all ethtool calls start with a cmd word */
433 if (copy_from_user(&cmd
, uaddr
, sizeof(u32
)))
437 case ETHTOOL_GDRVINFO
:
438 /* Copy out any request driver name */
439 if (copy_from_user(&info
, uaddr
, sizeof(info
)))
441 strncpy(drvname
, info
.driver
, sizeof(info
.driver
));
442 drvname
[sizeof(info
.driver
) - 1] = '\0';
444 /* clear struct for return */
445 memset(&info
, 0, sizeof(info
));
448 /* if requested, identify ourselves */
449 if (strcmp(drvname
, "?dhd") == 0) {
450 sprintf(info
.driver
, "dhd");
451 strcpy(info
.version
, BRCMF_VERSION_STR
);
454 /* otherwise, require dongle to be up */
455 else if (!drvr
->bus_if
->drvr_up
) {
456 brcmf_err("dongle is not up\n");
459 /* finally, report dongle driver type */
461 sprintf(info
.driver
, "wl");
463 sprintf(info
.version
, "%lu", drvr
->drv_version
);
464 if (copy_to_user(uaddr
, &info
, sizeof(info
)))
466 brcmf_dbg(TRACE
, "given %*s, returning %s\n",
467 (int)sizeof(drvname
), drvname
, info
.driver
);
470 /* Get toe offload components from dongle */
471 case ETHTOOL_GRXCSUM
:
472 case ETHTOOL_GTXCSUM
:
473 ret
= brcmf_fil_iovar_int_get(ifp
, "toe_ol", &toe_cmpnt
);
478 (cmd
== ETHTOOL_GTXCSUM
) ? TOE_TX_CSUM_OL
: TOE_RX_CSUM_OL
;
481 edata
.data
= (toe_cmpnt
& csum_dir
) ? 1 : 0;
483 if (copy_to_user(uaddr
, &edata
, sizeof(edata
)))
487 /* Set toe offload components in dongle */
488 case ETHTOOL_SRXCSUM
:
489 case ETHTOOL_STXCSUM
:
490 if (copy_from_user(&edata
, uaddr
, sizeof(edata
)))
493 /* Read the current settings, update and write back */
494 ret
= brcmf_fil_iovar_int_get(ifp
, "toe_ol", &toe_cmpnt
);
499 (cmd
== ETHTOOL_STXCSUM
) ? TOE_TX_CSUM_OL
: TOE_RX_CSUM_OL
;
502 toe_cmpnt
|= csum_dir
;
504 toe_cmpnt
&= ~csum_dir
;
506 ret
= brcmf_toe_set(ifp
, toe_cmpnt
);
510 /* If setting TX checksum mode, tell Linux the new mode */
511 if (cmd
== ETHTOOL_STXCSUM
) {
513 ifp
->ndev
->features
|= NETIF_F_IP_CSUM
;
515 ifp
->ndev
->features
&= ~NETIF_F_IP_CSUM
;
527 static int brcmf_netdev_ioctl_entry(struct net_device
*ndev
, struct ifreq
*ifr
,
530 struct brcmf_if
*ifp
= netdev_priv(ndev
);
531 struct brcmf_pub
*drvr
= ifp
->drvr
;
533 brcmf_dbg(TRACE
, "ifidx %d, cmd 0x%04x\n", ifp
->idx
, cmd
);
535 if (!drvr
->iflist
[ifp
->idx
])
538 if (cmd
== SIOCETHTOOL
)
539 return brcmf_ethtool(ifp
, ifr
->ifr_data
);
544 static int brcmf_netdev_stop(struct net_device
*ndev
)
546 struct brcmf_if
*ifp
= netdev_priv(ndev
);
547 struct brcmf_pub
*drvr
= ifp
->drvr
;
549 brcmf_dbg(TRACE
, "Enter\n");
551 if (drvr
->bus_if
->drvr_up
== 0)
554 brcmf_cfg80211_down(ndev
);
556 /* Set state and stop OS transmissions */
557 drvr
->bus_if
->drvr_up
= false;
558 netif_stop_queue(ndev
);
563 static int brcmf_netdev_open(struct net_device
*ndev
)
565 struct brcmf_if
*ifp
= netdev_priv(ndev
);
566 struct brcmf_pub
*drvr
= ifp
->drvr
;
567 struct brcmf_bus
*bus_if
= drvr
->bus_if
;
571 brcmf_dbg(TRACE
, "ifidx %d\n", ifp
->idx
);
573 /* If bus is not ready, can't continue */
574 if (bus_if
->state
!= BRCMF_BUS_DATA
) {
575 brcmf_err("failed bus is not ready\n");
579 atomic_set(&drvr
->pend_8021x_cnt
, 0);
581 memcpy(ndev
->dev_addr
, drvr
->mac
, ETH_ALEN
);
583 /* Get current TOE mode from dongle */
584 if (brcmf_fil_iovar_int_get(ifp
, "toe_ol", &toe_ol
) >= 0
585 && (toe_ol
& TOE_TX_CSUM_OL
) != 0)
586 drvr
->iflist
[ifp
->idx
]->ndev
->features
|=
589 drvr
->iflist
[ifp
->idx
]->ndev
->features
&=
592 /* make sure RF is ready for work */
593 brcmf_fil_cmd_int_set(ifp
, BRCMF_C_UP
, 0);
595 /* Allow transmit calls */
596 netif_start_queue(ndev
);
597 drvr
->bus_if
->drvr_up
= true;
598 if (brcmf_cfg80211_up(ndev
)) {
599 brcmf_err("failed to bring up cfg80211\n");
606 static const struct net_device_ops brcmf_netdev_ops_pri
= {
607 .ndo_open
= brcmf_netdev_open
,
608 .ndo_stop
= brcmf_netdev_stop
,
609 .ndo_get_stats
= brcmf_netdev_get_stats
,
610 .ndo_do_ioctl
= brcmf_netdev_ioctl_entry
,
611 .ndo_start_xmit
= brcmf_netdev_start_xmit
,
612 .ndo_set_mac_address
= brcmf_netdev_set_mac_address
,
613 .ndo_set_rx_mode
= brcmf_netdev_set_multicast_list
616 static const struct net_device_ops brcmf_netdev_ops_virt
= {
617 .ndo_open
= brcmf_cfg80211_up
,
618 .ndo_stop
= brcmf_cfg80211_down
,
619 .ndo_get_stats
= brcmf_netdev_get_stats
,
620 .ndo_do_ioctl
= brcmf_netdev_ioctl_entry
,
621 .ndo_start_xmit
= brcmf_netdev_start_xmit
,
622 .ndo_set_mac_address
= brcmf_netdev_set_mac_address
,
623 .ndo_set_rx_mode
= brcmf_netdev_set_multicast_list
626 int brcmf_net_attach(struct brcmf_if
*ifp
)
628 struct brcmf_pub
*drvr
= ifp
->drvr
;
629 struct net_device
*ndev
;
631 brcmf_dbg(TRACE
, "ifidx %d mac %pM\n", ifp
->idx
, ifp
->mac_addr
);
634 /* set appropriate operations */
636 ndev
->netdev_ops
= &brcmf_netdev_ops_pri
;
638 ndev
->netdev_ops
= &brcmf_netdev_ops_virt
;
640 ndev
->hard_header_len
= ETH_HLEN
+ drvr
->hdrlen
;
641 ndev
->ethtool_ops
= &brcmf_ethtool_ops
;
643 drvr
->rxsz
= ndev
->mtu
+ ndev
->hard_header_len
+
646 /* set the mac address */
647 memcpy(ndev
->dev_addr
, ifp
->mac_addr
, ETH_ALEN
);
649 if (register_netdev(ndev
) != 0) {
650 brcmf_err("couldn't register the net device\n");
654 brcmf_dbg(INFO
, "%s: Broadcom Dongle Host Driver\n", ndev
->name
);
659 ndev
->netdev_ops
= NULL
;
663 struct brcmf_if
*brcmf_add_if(struct brcmf_pub
*drvr
, int ifidx
, s32 bssidx
,
664 char *name
, u8
*addr_mask
)
666 struct brcmf_if
*ifp
;
667 struct net_device
*ndev
;
670 brcmf_dbg(TRACE
, "idx %d\n", ifidx
);
672 ifp
= drvr
->iflist
[ifidx
];
674 * Delete the existing interface before overwriting it
675 * in case we missed the BRCMF_E_IF_DEL event.
678 brcmf_err("ERROR: netdev:%s already exists\n",
681 netif_stop_queue(ifp
->ndev
);
682 unregister_netdev(ifp
->ndev
);
683 free_netdev(ifp
->ndev
);
684 drvr
->iflist
[ifidx
] = NULL
;
686 brcmf_err("ignore IF event\n");
687 return ERR_PTR(-EINVAL
);
691 /* Allocate netdev, including space for private structure */
692 ndev
= alloc_netdev(sizeof(struct brcmf_if
), name
, ether_setup
);
694 brcmf_err("OOM - alloc_netdev\n");
695 return ERR_PTR(-ENOMEM
);
698 ifp
= netdev_priv(ndev
);
701 drvr
->iflist
[ifidx
] = ifp
;
703 ifp
->bssidx
= bssidx
;
705 INIT_WORK(&ifp
->setmacaddr_work
, _brcmf_set_mac_address
);
706 INIT_WORK(&ifp
->multicast_work
, _brcmf_set_multicast_list
);
708 if (addr_mask
!= NULL
)
709 for (i
= 0; i
< ETH_ALEN
; i
++)
710 ifp
->mac_addr
[i
] = drvr
->mac
[i
] ^ addr_mask
[i
];
712 brcmf_dbg(TRACE
, " ==== pid:%x, if:%s (%pM) created ===\n",
713 current
->pid
, ifp
->ndev
->name
, ifp
->mac_addr
);
718 void brcmf_del_if(struct brcmf_pub
*drvr
, int ifidx
)
720 struct brcmf_if
*ifp
;
722 brcmf_dbg(TRACE
, "idx %d\n", ifidx
);
724 ifp
= drvr
->iflist
[ifidx
];
726 brcmf_err("Null interface\n");
731 if (ifp
->ndev
->netdev_ops
== &brcmf_netdev_ops_pri
) {
733 brcmf_netdev_stop(ifp
->ndev
);
737 netif_stop_queue(ifp
->ndev
);
740 cancel_work_sync(&ifp
->setmacaddr_work
);
741 cancel_work_sync(&ifp
->multicast_work
);
743 unregister_netdev(ifp
->ndev
);
744 drvr
->iflist
[ifidx
] = NULL
;
746 brcmf_cfg80211_detach(drvr
->config
);
747 free_netdev(ifp
->ndev
);
751 int brcmf_attach(uint bus_hdrlen
, struct device
*dev
)
753 struct brcmf_pub
*drvr
= NULL
;
756 brcmf_dbg(TRACE
, "Enter\n");
758 /* Allocate primary brcmf_info */
759 drvr
= kzalloc(sizeof(struct brcmf_pub
), GFP_ATOMIC
);
763 mutex_init(&drvr
->proto_block
);
765 /* Link to bus module */
766 drvr
->hdrlen
= bus_hdrlen
;
767 drvr
->bus_if
= dev_get_drvdata(dev
);
768 drvr
->bus_if
->drvr
= drvr
;
770 /* create device debugfs folder */
771 brcmf_debugfs_attach(drvr
);
773 /* Attach and link in the protocol */
774 ret
= brcmf_proto_attach(drvr
);
776 brcmf_err("brcmf_prot_attach failed\n");
780 /* attach firmware event handler */
781 brcmf_fweh_attach(drvr
);
783 INIT_LIST_HEAD(&drvr
->bus_if
->dcmd_list
);
785 init_waitqueue_head(&drvr
->pend_8021x_wait
);
795 int brcmf_bus_start(struct device
*dev
)
798 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
799 struct brcmf_pub
*drvr
= bus_if
->drvr
;
800 struct brcmf_if
*ifp
;
802 brcmf_dbg(TRACE
, "\n");
804 /* Bring up the bus */
805 ret
= brcmf_bus_init(bus_if
);
807 brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret
);
811 /* add primary networking interface */
812 ifp
= brcmf_add_if(drvr
, 0, 0, "wlan%d", NULL
);
816 /* signal bus ready */
817 bus_if
->state
= BRCMF_BUS_DATA
;
819 /* Bus is ready, do any initialization */
820 ret
= brcmf_c_preinit_dcmds(ifp
);
824 drvr
->config
= brcmf_cfg80211_attach(drvr
, bus_if
->dev
);
825 if (drvr
->config
== NULL
) {
830 ret
= brcmf_fweh_activate_events(ifp
);
834 ret
= brcmf_net_attach(ifp
);
837 brcmf_err("failed: %d\n", ret
);
839 brcmf_cfg80211_detach(drvr
->config
);
840 free_netdev(drvr
->iflist
[0]->ndev
);
841 drvr
->iflist
[0] = NULL
;
848 static void brcmf_bus_detach(struct brcmf_pub
*drvr
)
850 brcmf_dbg(TRACE
, "Enter\n");
853 /* Stop the protocol module */
854 brcmf_proto_stop(drvr
);
856 /* Stop the bus module */
857 brcmf_bus_stop(drvr
->bus_if
);
861 void brcmf_dev_reset(struct device
*dev
)
863 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
864 struct brcmf_pub
*drvr
= bus_if
->drvr
;
869 brcmf_fil_cmd_int_set(drvr
->iflist
[0], BRCMF_C_TERMINATED
, 1);
872 void brcmf_detach(struct device
*dev
)
875 struct brcmf_bus
*bus_if
= dev_get_drvdata(dev
);
876 struct brcmf_pub
*drvr
= bus_if
->drvr
;
878 brcmf_dbg(TRACE
, "Enter\n");
883 /* stop firmware event handling */
884 brcmf_fweh_detach(drvr
);
886 /* make sure primary interface removed last */
887 for (i
= BRCMF_MAX_IFS
-1; i
> -1; i
--)
889 brcmf_del_if(drvr
, i
);
891 brcmf_bus_detach(drvr
);
894 brcmf_proto_detach(drvr
);
897 brcmf_debugfs_detach(drvr
);
902 static int brcmf_get_pend_8021x_cnt(struct brcmf_pub
*drvr
)
904 return atomic_read(&drvr
->pend_8021x_cnt
);
907 int brcmf_netdev_wait_pend8021x(struct net_device
*ndev
)
909 struct brcmf_if
*ifp
= netdev_priv(ndev
);
910 struct brcmf_pub
*drvr
= ifp
->drvr
;
913 err
= wait_event_timeout(drvr
->pend_8021x_wait
,
914 !brcmf_get_pend_8021x_cnt(drvr
),
915 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX
));
922 static void brcmf_driver_init(struct work_struct
*work
)
924 brcmf_debugfs_init();
926 #ifdef CONFIG_BRCMFMAC_SDIO
929 #ifdef CONFIG_BRCMFMAC_USB
933 static DECLARE_WORK(brcmf_driver_work
, brcmf_driver_init
);
935 static int __init
brcmfmac_module_init(void)
937 if (!schedule_work(&brcmf_driver_work
))
943 static void __exit
brcmfmac_module_exit(void)
945 cancel_work_sync(&brcmf_driver_work
);
947 #ifdef CONFIG_BRCMFMAC_SDIO
950 #ifdef CONFIG_BRCMFMAC_USB
953 brcmf_debugfs_exit();
956 module_init(brcmfmac_module_init
);
957 module_exit(brcmfmac_module_exit
);