struct mutex proto_block;
- /* Thread to issue ioctl for multicast */
- struct task_struct *sysioc_tsk;
- wait_queue_head_t sysioc_waitq;
- bool set_multicast;
- bool set_macaddress;
+ struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
u8 macvalue[ETH_ALEN];
atomic_t pend_8021x_cnt;
};
/* Error bits */
module_param(brcmf_msg_level, int, 0);
-/* Spawn a thread for system ioctls (set mac, set mcast) */
-uint brcmf_sysioc = true;
-module_param(brcmf_sysioc, uint, 0);
-
-/* ARP offload agent mode : Enable ARP Host Auto-Reply
-and ARP Peer Auto-Reply */
-uint brcmf_arp_mode = 0xb;
-module_param(brcmf_arp_mode, uint, 0);
-
-/* ARP offload enable */
-uint brcmf_arp_enable = true;
-module_param(brcmf_arp_enable, uint, 0);
-
-/* Global Pkt filter enable control */
-uint brcmf_pkt_filter_enable = true;
-module_param(brcmf_pkt_filter_enable, uint, 0);
-
-/* Pkt filter init setup */
-uint brcmf_pkt_filter_init;
-module_param(brcmf_pkt_filter_init, uint, 0);
-
-/* Pkt filter mode control */
-uint brcmf_master_mode = true;
-module_param(brcmf_master_mode, uint, 0);
-
-/* Contorl fw roaming */
-uint brcmf_roam = 1;
-
-/* Control radio state */
-uint brcmf_radio_up = 1;
-
-/* Network inteface name */
-char iface_name[IFNAMSIZ] = "wlan";
-module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
-
-/* The following are specific to the SDIO dongle */
-
-#ifdef SDTEST
-/* Echo packet generator (pkts/s) */
-uint brcmf_pktgen;
-module_param(brcmf_pktgen, uint, 0);
-
-/* Echo packet len (0 => sawtooth, max 2040) */
-uint brcmf_pktgen_len;
-module_param(brcmf_pktgen_len, uint, 0);
-#endif
-
-static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol);
-static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol);
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
- void *pktdata, struct brcmf_event_msg *event_ptr,
- void **data_ptr);
static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
{
return "<if_none>";
}
-static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
+static void _brcmf_set_multicast_list(struct work_struct *work)
{
struct net_device *dev;
struct netdev_hw_addr *ha;
u32 allmulti, cnt;
+ __le32 cnt_le;
+ __le32 allmulti_le;
struct brcmf_ioctl ioc;
char *buf, *bufp;
uint buflen;
int ret;
- dev = drvr_priv->iflist[ifidx]->net;
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ multicast_work);
+
+ dev = drvr_priv->iflist[0]->net;
cnt = netdev_mc_count(dev);
/* Determine initial value of allmulti flag */
buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
bufp = buf = kmalloc(buflen, GFP_ATOMIC);
- if (!bufp) {
- brcmf_dbg(ERROR, "%s: out of memory for mcast_list, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt);
+ if (!bufp)
return;
- }
strcpy(bufp, "mcast_list");
bufp += strlen("mcast_list") + 1;
- cnt = cpu_to_le32(cnt);
- memcpy(bufp, &cnt, sizeof(cnt));
- bufp += sizeof(cnt);
+ cnt_le = cpu_to_le32(cnt);
+ memcpy(bufp, &cnt_le, sizeof(cnt));
+ bufp += sizeof(cnt_le);
netdev_for_each_mc_addr(ha, dev) {
if (!cnt)
ioc.len = buflen;
ioc.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, 0, &ioc, ioc.len);
if (ret < 0) {
brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt);
+ brcmf_ifname(&drvr_priv->pub, 0), cnt);
allmulti = cnt ? true : allmulti;
}
buflen = sizeof("allmulti") + sizeof(allmulti);
buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- brcmf_dbg(ERROR, "%s: out of memory for allmulti\n",
- brcmf_ifname(&drvr_priv->pub, ifidx));
+ if (!buf)
return;
- }
- allmulti = cpu_to_le32(allmulti);
+
+ allmulti_le = cpu_to_le32(allmulti);
if (!brcmu_mkiovar
- ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
+ ("allmulti", (void *)&allmulti_le,
+ sizeof(allmulti_le), buf, buflen)) {
brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
+ brcmf_ifname(&drvr_priv->pub, 0),
(int)sizeof(allmulti), buflen);
kfree(buf);
return;
ioc.len = buflen;
ioc.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, 0, &ioc, ioc.len);
if (ret < 0) {
brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti));
+ brcmf_ifname(&drvr_priv->pub, 0),
+ le32_to_cpu(allmulti_le));
}
kfree(buf);
driver does */
allmulti = (dev->flags & IFF_PROMISC) ? true : false;
- allmulti = cpu_to_le32(allmulti);
+ allmulti_le = cpu_to_le32(allmulti);
memset(&ioc, 0, sizeof(ioc));
ioc.cmd = BRCMF_C_SET_PROMISC;
- ioc.buf = &allmulti;
- ioc.len = sizeof(allmulti);
+ ioc.buf = &allmulti_le;
+ ioc.len = sizeof(allmulti_le);
ioc.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, 0, &ioc, ioc.len);
if (ret < 0) {
brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti));
+ brcmf_ifname(&drvr_priv->pub, 0),
+ le32_to_cpu(allmulti_le));
}
}
-static int
-_brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
+static void
+_brcmf_set_mac_address(struct work_struct *work)
{
char buf[32];
struct brcmf_ioctl ioc;
int ret;
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ setmacaddr_work);
+
brcmf_dbg(TRACE, "enter\n");
- if (!brcmu_mkiovar("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
+ if (!brcmu_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
+ ETH_ALEN, buf, 32)) {
brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
- brcmf_ifname(&drvr_priv->pub, ifidx));
- return -1;
+ brcmf_ifname(&drvr_priv->pub, 0));
+ return;
}
memset(&ioc, 0, sizeof(ioc));
ioc.cmd = BRCMF_C_SET_VAR;
ioc.len = 32;
ioc.set = true;
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, 0, &ioc, ioc.len);
if (ret < 0)
brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx));
+ brcmf_ifname(&drvr_priv->pub, 0));
else
- memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
+ memcpy(drvr_priv->iflist[0]->net->dev_addr,
+ drvr_priv->macvalue, ETH_ALEN);
- return ret;
+ return;
}
-#ifdef SOFTAP
-static struct net_device *ap_net_dev;
-#endif
-
/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
static void brcmf_op_if(struct brcmf_if *ifp)
{
unregister_netdev(ifp->net);
free_netdev(ifp->net);
}
- /* Allocate etherdev, including space for private structure */
- ifp->net = alloc_etherdev(sizeof(drvr_priv));
+ /* Allocate netdev, including space for private structure */
+ ifp->net = alloc_netdev(sizeof(drvr_priv), "wlan%d",
+ ether_setup);
if (!ifp->net) {
- brcmf_dbg(ERROR, "OOM - alloc_etherdev\n");
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
ret = -ENOMEM;
}
if (ret == 0) {
err);
ret = -EOPNOTSUPP;
} else {
-#ifdef SOFTAP
- /* semaphore that the soft AP CODE
- waits on */
- struct semaphore ap_eth_sema;
-
- /* save ptr to wl0.1 netdev for use
- in wl_iw.c */
- ap_net_dev = ifp->net;
- /* signal to the SOFTAP 'sleeper' thread,
- wl0.1 is ready */
- up(&ap_eth_sema);
-#endif
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
current->pid, ifp->net->name);
ifp->state = 0;
drvr_priv->iflist[ifp->idx] = NULL;
kfree(ifp);
-#ifdef SOFTAP
- if (ifp->net == ap_net_dev)
- ap_net_dev = NULL; /* NULL SOFTAP global
- wl0.1 as well */
-#endif /* SOFTAP */
- }
-}
-
-static int _brcmf_sysioc_thread(void *data)
-{
- struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
- int i;
-#ifdef SOFTAP
- bool in_ap = false;
-#endif
- DECLARE_WAITQUEUE(wait, current);
- allow_signal(SIGTERM);
-
- add_wait_queue(&drvr_priv->sysioc_waitq, &wait);
- while (1) {
- prepare_to_wait(&drvr_priv->sysioc_waitq, &wait,
- TASK_INTERRUPTIBLE);
-
- /* wait for event */
- schedule();
-
- if (kthread_should_stop())
- break;
-
- for (i = 0; i < BRCMF_MAX_IFS; i++) {
- struct brcmf_if *ifentry = drvr_priv->iflist[i];
- if (ifentry) {
-#ifdef SOFTAP
- in_ap = (ap_net_dev != NULL);
-#endif /* SOFTAP */
- if (ifentry->state)
- brcmf_op_if(ifentry);
-#ifdef SOFTAP
- if (drvr_priv->iflist[i] == NULL) {
- brcmf_dbg(TRACE, "interface %d removed!\n",
- i);
- continue;
- }
-
- if (in_ap && drvr_priv->set_macaddress) {
- brcmf_dbg(TRACE, "attempt to set MAC for %s in AP Mode, blocked.\n",
- ifentry->net->name);
- drvr_priv->set_macaddress = false;
- continue;
- }
-
- if (in_ap && drvr_priv->set_multicast) {
- brcmf_dbg(TRACE, "attempt to set MULTICAST list for %s in AP Mode, blocked.\n",
- ifentry->net->name);
- drvr_priv->set_multicast = false;
- continue;
- }
-#endif /* SOFTAP */
- if (drvr_priv->set_multicast) {
- drvr_priv->set_multicast = false;
- _brcmf_set_multicast_list(drvr_priv, i);
- }
- if (drvr_priv->set_macaddress) {
- drvr_priv->set_macaddress = false;
- _brcmf_set_mac_address(drvr_priv, i,
- drvr_priv->macvalue);
- }
- }
- }
}
- finish_wait(&drvr_priv->sysioc_waitq, &wait);
- return 0;
}
static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
{
- int ret = 0;
-
struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
return -1;
memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
- drvr_priv->set_macaddress = true;
- wake_up(&drvr_priv->sysioc_waitq);
- return ret;
+ schedule_work(&drvr_priv->setmacaddr_work);
+ return 0;
}
static void brcmf_netdev_set_multicast_list(struct net_device *dev)
if (ifidx == BRCMF_BAD_IF)
return;
- drvr_priv->set_multicast = true;
- wake_up(&drvr_priv->sysioc_waitq);
+ schedule_work(&drvr_priv->multicast_work);
}
int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
netif_wake_queue(net);
}
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
+ void *pktdata, struct brcmf_event_msg *event,
+ void **data)
+{
+ int bcmerror = 0;
+
+ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
+ if (bcmerror != 0)
+ return bcmerror;
+
+ if (drvr_priv->iflist[*ifidx]->net)
+ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
+ event, *data);
+
+ return bcmerror;
+}
+
void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
int numpkt)
{
ioc.set = false;
strcpy(buf, "toe_ol");
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.len);
if (ret < 0) {
/* Check for older dongle image that doesn't support toe_ol */
if (ret == -EIO) {
strcpy(buf, "toe_ol");
memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.len);
if (ret < 0) {
brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
brcmf_ifname(&drvr_priv->pub, ifidx), ret);
strcpy(buf, "toe");
memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
+ ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.len);
if (ret < 0) {
brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
brcmf_ifname(&drvr_priv->pub, ifidx), ret);
sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
sprintf(info->bus_info, "%s",
- dev_name(&brcmf_cfg80211_get_sdio_func()->dev));
+ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus)));
}
-struct ethtool_ops brcmf_ethtool_ops = {
+static struct ethtool_ops brcmf_ethtool_ops = {
.get_drvinfo = brcmf_ethtool_get_drvinfo
};
-static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
{
struct ethtool_drvinfo info;
char drvname[sizeof(info.driver)];
int cmd)
{
struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- struct brcmf_c_ioctl ioc;
- int bcmerror = 0;
- int buflen = 0;
- void *buf = NULL;
- uint driver = 0;
int ifidx;
- bool is_set_key_cmd;
ifidx = brcmf_net2idx(drvr_priv, net);
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
if (cmd == SIOCETHTOOL)
return brcmf_ethtool(drvr_priv, ifr->ifr_data);
- if (cmd != SIOCDEVPRIVATE)
- return -EOPNOTSUPP;
-
- memset(&ioc, 0, sizeof(ioc));
-
- /* Copy the ioc control structure part of ioctl request */
- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) {
- bcmerror = -EINVAL;
- goto done;
- }
-
- /* Copy out any buffer passed */
- if (ioc.buf) {
- buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
- /* optimization for direct ioctl calls from kernel */
- /*
- if (segment_eq(get_fs(), KERNEL_DS)) {
- buf = ioc.buf;
- } else {
- */
- {
- buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- bcmerror = -ENOMEM;
- goto done;
- }
- if (copy_from_user(buf, ioc.buf, buflen)) {
- bcmerror = -EINVAL;
- goto done;
- }
- }
- }
+ return -EOPNOTSUPP;
+}
- /* To differentiate read 4 more byes */
- if ((copy_from_user(&driver, (char *)ifr->ifr_data +
- sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) {
- bcmerror = -EINVAL;
- goto done;
- }
+/* called only from within this driver */
+int brcmf_netdev_ioctl_priv(struct net_device *net, struct brcmf_ioctl *ioc)
+{
+ int bcmerror = 0;
+ int buflen = 0;
+ bool is_set_key_cmd;
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ int ifidx;
- if (!capable(CAP_NET_ADMIN)) {
- bcmerror = -EPERM;
- goto done;
- }
+ ifidx = brcmf_net2idx(drvr_priv, net);
- /* check for local brcmf ioctl and handle it */
- if (driver == BRCMF_IOCTL_MAGIC) {
- bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc,
- buf, buflen);
- if (bcmerror)
- drvr_priv->pub.bcmerror = bcmerror;
- goto done;
- }
+ if (ioc->buf != NULL)
+ buflen = min_t(uint, ioc->len, BRCMF_IOCTL_MAXLEN);
/* send to dongle (must be up, and wl) */
if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
* Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
* set key IOCTL to prevent M4 encryption.
*/
- is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("wsec_key", ioc.buf, 9))) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
+ is_set_key_cmd = ((ioc->cmd == BRCMF_C_SET_KEY) ||
+ ((ioc->cmd == BRCMF_C_SET_VAR) &&
+ !(strncmp("wsec_key", ioc->buf, 9))) ||
+ ((ioc->cmd == BRCMF_C_SET_VAR) &&
+ !(strncmp("bsscfg:wsec_key", ioc->buf, 15))));
if (is_set_key_cmd)
brcmf_netdev_wait_pend8021x(net);
- bcmerror = brcmf_proto_ioctl(&drvr_priv->pub, ifidx,
- (struct brcmf_ioctl *)&ioc, buf, buflen);
+ bcmerror = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, ioc, buflen);
done:
- if (!bcmerror && buf && ioc.buf) {
- if (copy_to_user(ioc.buf, buf, buflen))
- bcmerror = -EFAULT;
- }
-
- kfree(buf);
-
if (bcmerror > 0)
bcmerror = 0;
static int brcmf_netdev_stop(struct net_device *net)
{
-#if !defined(IGNORE_ETH0_DOWN)
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(net);
brcmf_dbg(TRACE, "Enter\n");
- brcmf_cfg80211_down();
- if (drvr_priv->pub.up == 0)
+ brcmf_cfg80211_down(drvr->config);
+ if (drvr->up == 0)
return 0;
/* Set state and stop OS transmissions */
- drvr_priv->pub.up = 0;
+ drvr->up = 0;
netif_stop_queue(net);
-#else
- brcmf_dbg(ERROR, "BYPASSed due to BRCM compilation: under investigation\n");
-#endif /* !defined(IGNORE_ETH0_DOWN) */
return 0;
}
/* Allow transmit calls */
netif_start_queue(net);
drvr_priv->pub.up = 1;
- if (unlikely(brcmf_cfg80211_up())) {
+ if (brcmf_cfg80211_up(drvr_priv->pub.config)) {
brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
return -1;
}
ifp = drvr_priv->iflist[ifidx];
if (!ifp) {
ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
- if (!ifp) {
- brcmf_dbg(ERROR, "OOM - struct brcmf_if\n");
+ if (!ifp)
return -ENOMEM;
- }
}
memset(ifp, 0, sizeof(struct brcmf_if));
if (net == NULL) {
ifp->state = BRCMF_E_IF_ADD;
ifp->idx = ifidx;
- wake_up(&drvr_priv->sysioc_waitq);
+ brcmf_op_if(ifp);
} else
ifp->net = net;
ifp->state = BRCMF_E_IF_DEL;
ifp->idx = ifidx;
- wake_up(&drvr_priv->sysioc_waitq);
+ brcmf_op_if(ifp);
}
struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
brcmf_dbg(TRACE, "Enter\n");
- /* Allocate etherdev, including space for private structure */
- net = alloc_etherdev(sizeof(drvr_priv));
+ /* Allocate netdev, including space for private structure */
+ net = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
if (!net) {
- brcmf_dbg(ERROR, "OOM - alloc_etherdev\n");
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
goto fail;
}
/* Allocate primary brcmf_info */
drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
- if (!drvr_priv) {
- brcmf_dbg(ERROR, "OOM - alloc brcmf_info\n");
+ if (!drvr_priv)
goto fail;
- }
/*
* Save the brcmf_info into the priv
*/
memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
- /* Set network interface name if it was provided as module parameter */
- if (iface_name[0]) {
- int len;
- char ch;
- strncpy(net->name, iface_name, IFNAMSIZ);
- net->name[IFNAMSIZ - 1] = 0;
- len = strlen(net->name);
- ch = net->name[len - 1];
- if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
- strcat(net->name, "%d");
- }
-
if (brcmf_add_if(drvr_priv, 0, net, net->name, NULL, 0, 0) ==
BRCMF_BAD_IF)
goto fail;
}
/* Attach and link in the cfg80211 */
- if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
+ drvr_priv->pub.config =
+ brcmf_cfg80211_attach(net,
+ brcmf_bus_get_device(bus),
+ &drvr_priv->pub);
+ if (drvr_priv->pub.config == NULL) {
brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
goto fail;
}
- if (brcmf_sysioc) {
- init_waitqueue_head(&drvr_priv->sysioc_waitq);
- drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread,
- drvr_priv, "_brcmf_sysioc");
- if (IS_ERR(drvr_priv->sysioc_tsk)) {
- printk(KERN_WARNING
- "_brcmf_sysioc thread failed to start\n");
- drvr_priv->sysioc_tsk = NULL;
- }
- } else
- drvr_priv->sysioc_tsk = NULL;
+ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
/*
* Save the brcmf_info into the priv
unregister_netdev(ifp->net);
}
- if (drvr_priv->sysioc_tsk) {
- send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
- kthread_stop(drvr_priv->sysioc_tsk);
- drvr_priv->sysioc_tsk = NULL;
- }
+ cancel_work_sync(&drvr_priv->setmacaddr_work);
+ cancel_work_sync(&drvr_priv->multicast_work);
brcmf_bus_detach(drvr);
if (drvr->prot)
brcmf_proto_detach(drvr);
- brcmf_cfg80211_detach();
+ brcmf_cfg80211_detach(drvr->config);
free_netdev(ifp->net);
kfree(ifp);
return 0;
}
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
- void *pktdata, struct brcmf_event_msg *event,
- void **data)
-{
- int bcmerror = 0;
-
- bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
- if (bcmerror != 0)
- return bcmerror;
-
- if (drvr_priv->iflist[*ifidx]->net)
- brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
- event, *data);
-
- return bcmerror;
-}
-
-int brcmf_netdev_reset(struct net_device *dev, u8 flag)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
-
- brcmf_bus_devreset(&drvr_priv->pub, flag);
-
- return 1;
-}
-
static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
{
return atomic_read(&drvr_priv->pend_8021x_cnt);