dhd_linux.c 21.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (c) 2010 Broadcom Corporation
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <linux/kernel.h>
#include <linux/etherdevice.h>
19
#include <linux/module.h>
20 21 22 23 24 25 26 27 28 29
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>

#include "dhd.h"
#include "dhd_bus.h"
#include "dhd_proto.h"
#include "dhd_dbg.h"
#include "wl_cfg80211.h"
30
#include "fwil.h"
31 32

MODULE_AUTHOR("Broadcom Corporation");
H
Hante Meuleman 已提交
33 34
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
35 36
MODULE_LICENSE("Dual BSD/GPL");

37
#define MAX_WAIT_FOR_8021X_TX		50	/* msecs */
38 39

/* Error bits */
40
int brcmf_msg_level;
41 42 43 44 45 46
module_param(brcmf_msg_level, int, 0);


char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
{
	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
47
		brcmf_err("ifidx %d out of range\n", ifidx);
48 49 50
		return "<if_bad>";
	}

51
	if (drvr->iflist[ifidx] == NULL) {
52
		brcmf_err("null i/f %d\n", ifidx);
53 54 55
		return "<if_null>";
	}

56 57
	if (drvr->iflist[ifidx]->ndev)
		return drvr->iflist[ifidx]->ndev->name;
58 59 60 61 62 63

	return "<if_none>";
}

static void _brcmf_set_multicast_list(struct work_struct *work)
{
64
	struct brcmf_if *ifp;
65 66
	struct net_device *ndev;
	struct netdev_hw_addr *ha;
67
	u32 cmd_value, cnt;
68 69
	__le32 cnt_le;
	char *buf, *bufp;
70 71
	u32 buflen;
	s32 err;
72

73 74
	brcmf_dbg(TRACE, "enter\n");

75
	ifp = container_of(work, struct brcmf_if, multicast_work);
76
	ndev = ifp->ndev;
77 78

	/* Determine initial value of allmulti flag */
79
	cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
80 81

	/* Send down the multicast list first. */
82 83 84 85
	cnt = netdev_mc_count(ndev);
	buflen = sizeof(cnt) + (cnt * ETH_ALEN);
	buf = kmalloc(buflen, GFP_ATOMIC);
	if (!buf)
86
		return;
87
	bufp = buf;
88 89

	cnt_le = cpu_to_le32(cnt);
90
	memcpy(bufp, &cnt_le, sizeof(cnt_le));
91 92 93 94 95 96 97 98 99 100
	bufp += sizeof(cnt_le);

	netdev_for_each_mc_addr(ha, ndev) {
		if (!cnt)
			break;
		memcpy(bufp, ha->addr, ETH_ALEN);
		bufp += ETH_ALEN;
		cnt--;
	}

101 102
	err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
	if (err < 0) {
103
		brcmf_err("Setting mcast_list failed, %d\n", err);
104
		cmd_value = cnt ? true : cmd_value;
105 106 107 108
	}

	kfree(buf);

109 110
	/*
	 * Now send the allmulti setting.  This is based on the setting in the
111 112 113
	 * net_device flags, but might be modified above to be turned on if we
	 * were trying to set some addresses and dongle rejected it...
	 */
114 115
	err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
	if (err < 0)
116
		brcmf_err("Setting allmulti failed, %d\n", err);
117 118 119 120 121

	/*Finally, pick up the PROMISC flag */
	cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
	if (err < 0)
122
		brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
123
			  err);
124 125 126 127 128
}

static void
_brcmf_set_mac_address(struct work_struct *work)
{
129 130
	struct brcmf_if *ifp;
	s32 err;
131 132 133

	brcmf_dbg(TRACE, "enter\n");

134 135
	ifp = container_of(work, struct brcmf_if, setmacaddr_work);
	err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
136 137
				       ETH_ALEN);
	if (err < 0) {
138
		brcmf_err("Setting cur_etheraddr failed, %d\n", err);
139 140
	} else {
		brcmf_dbg(TRACE, "MAC address updated to %pM\n",
141 142
			  ifp->mac_addr);
		memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
143
	}
144 145 146 147
}

static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{
148
	struct brcmf_if *ifp = netdev_priv(ndev);
149 150
	struct sockaddr *sa = (struct sockaddr *)addr;

151 152
	memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
	schedule_work(&ifp->setmacaddr_work);
153 154 155 156 157
	return 0;
}

static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{
158
	struct brcmf_if *ifp = netdev_priv(ndev);
159

160
	schedule_work(&ifp->multicast_work);
161 162
}

163 164
static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
					   struct net_device *ndev)
165 166
{
	int ret;
167
	struct brcmf_if *ifp = netdev_priv(ndev);
168
	struct brcmf_pub *drvr = ifp->drvr;
169
	struct ethhdr *eh;
170 171 172

	brcmf_dbg(TRACE, "Enter\n");

173 174 175
	/* Can the device send data? */
	if (drvr->bus_if->state != BRCMF_BUS_DATA) {
		brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
176
		netif_stop_queue(ndev);
177 178 179
		dev_kfree_skb(skb);
		ret = -ENODEV;
		goto done;
180 181
	}

182
	if (!drvr->iflist[ifp->idx]) {
183
		brcmf_err("bad ifidx %d\n", ifp->idx);
184
		netif_stop_queue(ndev);
185 186 187
		dev_kfree_skb(skb);
		ret = -ENODEV;
		goto done;
188 189 190
	}

	/* Make sure there's enough room for any header */
191
	if (skb_headroom(skb) < drvr->hdrlen) {
192 193 194
		struct sk_buff *skb2;

		brcmf_dbg(INFO, "%s: insufficient headroom\n",
195
			  brcmf_ifname(drvr, ifp->idx));
196
		drvr->bus_if->tx_realloc++;
197
		skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
198 199 200
		dev_kfree_skb(skb);
		skb = skb2;
		if (skb == NULL) {
201
			brcmf_err("%s: skb_realloc_headroom failed\n",
202
				  brcmf_ifname(drvr, ifp->idx));
203 204 205 206 207
			ret = -ENOMEM;
			goto done;
		}
	}

208 209 210 211 212
	/* validate length for ether packet */
	if (skb->len < sizeof(*eh)) {
		ret = -EINVAL;
		dev_kfree_skb(skb);
		goto done;
213 214
	}

215 216 217 218 219
	/* handle ethernet header */
	eh = (struct ethhdr *)(skb->data);
	if (is_multicast_ether_addr(eh->h_dest))
		drvr->tx_multicast++;
	if (ntohs(eh->h_proto) == ETH_P_PAE)
220
		atomic_inc(&ifp->pend_8021x_cnt);
221

222 223 224 225
	/* If the protocol uses a data header, apply it */
	brcmf_proto_hdrpush(drvr, ifp->idx, skb);

	/* Use bus module to send data frame */
A
Arend van Spriel 已提交
226
	ret =  brcmf_bus_txdata(drvr->bus_if, skb);
227 228

done:
229 230 231 232 233 234
	if (ret) {
		ifp->stats.tx_dropped++;
	} else {
		ifp->stats.tx_packets++;
		ifp->stats.tx_bytes += skb->len;
	}
235 236

	/* Return ok: we always eat the packet */
237
	return NETDEV_TX_OK;
238 239
}

240
void brcmf_txflowblock(struct device *dev, bool state)
241 242
{
	struct net_device *ndev;
243 244
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
245
	int i;
246 247 248

	brcmf_dbg(TRACE, "Enter\n");

249 250 251 252 253 254 255 256
	for (i = 0; i < BRCMF_MAX_IFS; i++)
		if (drvr->iflist[i]) {
			ndev = drvr->iflist[i]->ndev;
			if (state)
				netif_stop_queue(ndev);
			else
				netif_wake_queue(ndev);
		}
257 258
}

259
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
260 261 262
{
	unsigned char *eth;
	uint len;
263
	struct sk_buff *skb, *pnext;
264
	struct brcmf_if *ifp;
265 266
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
267 268
	u8 ifidx;
	int ret;
269 270 271

	brcmf_dbg(TRACE, "Enter\n");

272 273
	skb_queue_walk_safe(skb_list, skb, pnext) {
		skb_unlink(skb, skb_list);
274

275
		/* process and remove protocol-specific header */
276
		ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
277 278 279 280 281
		ifp = drvr->iflist[ifidx];

		if (ret || !ifp || !ifp->ndev) {
			if ((ret != -ENODATA) && ifp)
				ifp->stats.rx_errors++;
282 283 284 285
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
		/* Get the protocol, maintain skb around eth_type_trans()
		 * The main reason for this hack is for the limitation of
		 * Linux 2.4 where 'eth_type_trans' uses the
		 * 'net->hard_header_len'
		 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
		 * coping of the packet coming from the network stack to add
		 * BDC, Hardware header etc, during network interface
		 * registration
		 * we set the 'net->hard_header_len' to ETH_HLEN + extra space
		 * required
		 * for BDC, Hardware header etc. and not just the ETH_HLEN
		 */
		eth = skb->data;
		len = skb->len;

		skb->dev = ifp->ndev;
		skb->protocol = eth_type_trans(skb, skb->dev);

		if (skb->pkt_type == PACKET_MULTICAST)
305
			ifp->stats.multicast++;
306 307 308 309 310 311 312 313

		skb->data = eth;
		skb->len = len;

		/* Strip header, count, deliver upward */
		skb_pull(skb, ETH_HLEN);

		/* Process special event packets and then discard them */
314
		brcmf_fweh_process_skb(drvr, skb, &ifidx);
315

316 317
		if (drvr->iflist[ifidx]) {
			ifp = drvr->iflist[ifidx];
318
			ifp->ndev->last_rx = jiffies;
319
		}
320

321 322 323 324 325 326 327
		if (!(ifp->ndev->flags & IFF_UP)) {
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

		ifp->stats.rx_bytes += skb->len;
		ifp->stats.rx_packets++;
328 329 330 331 332 333 334 335 336 337 338 339 340 341

		if (in_interrupt())
			netif_rx(skb);
		else
			/* If the receive is not processed inside an ISR,
			 * the softirqd must be woken explicitly to service
			 * the NET_RX_SOFTIRQ.  In 2.6 kernels, this is handled
			 * by netif_rx_ni(), but in earlier kernels, we need
			 * to do it manually.
			 */
			netif_rx_ni(skb);
	}
}

342
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
343
{
344
	u8 ifidx;
345 346
	struct ethhdr *eh;
	u16 type;
347 348
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
349
	struct brcmf_if *ifp;
350

351
	brcmf_proto_hdrpull(drvr, &ifidx, txp);
352

353 354 355 356
	ifp = drvr->iflist[ifidx];
	if (!ifp)
		return;

357 358 359
	eh = (struct ethhdr *)(txp->data);
	type = ntohs(eh->h_proto);

360
	if (type == ETH_P_PAE) {
361 362 363
		atomic_dec(&ifp->pend_8021x_cnt);
		if (waitqueue_active(&ifp->pend_8021x_wait))
			wake_up(&ifp->pend_8021x_wait);
364
	}
365 366
	if (!success)
		ifp->stats.tx_errors++;
367 368 369 370
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
371
	struct brcmf_if *ifp = netdev_priv(ndev);
372 373 374 375 376 377

	brcmf_dbg(TRACE, "Enter\n");

	return &ifp->stats;
}

378 379 380 381 382
/*
 * Set current toe component enables in toe_ol iovar,
 * and set toe global enable iovar
 */
static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol)
383
{
384
	s32 err;
385

386 387
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
388
		brcmf_err("Setting toe_ol failed, %d\n", err);
389
		return err;
390 391
	}

392 393
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
394
		brcmf_err("Setting toe failed, %d\n", err);
395

396
	return err;
397 398 399 400 401 402

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
403
	struct brcmf_if *ifp = netdev_priv(ndev);
404
	struct brcmf_pub *drvr = ifp->drvr;
405 406

	sprintf(info->driver, KBUILD_MODNAME);
407
	sprintf(info->version, "%lu", drvr->drv_version);
A
Arend van Spriel 已提交
408
	sprintf(info->bus_info, "%s", dev_name(drvr->bus_if->dev));
409 410
}

411 412
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
413 414
};

415
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
416
{
417
	struct brcmf_pub *drvr = ifp->drvr;
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
	struct ethtool_drvinfo info;
	char drvname[sizeof(info.driver)];
	u32 cmd;
	struct ethtool_value edata;
	u32 toe_cmpnt, csum_dir;
	int ret;

	brcmf_dbg(TRACE, "Enter\n");

	/* all ethtool calls start with a cmd word */
	if (copy_from_user(&cmd, uaddr, sizeof(u32)))
		return -EFAULT;

	switch (cmd) {
	case ETHTOOL_GDRVINFO:
		/* Copy out any request driver name */
		if (copy_from_user(&info, uaddr, sizeof(info)))
			return -EFAULT;
		strncpy(drvname, info.driver, sizeof(info.driver));
		drvname[sizeof(info.driver) - 1] = '\0';

		/* clear struct for return */
		memset(&info, 0, sizeof(info));
		info.cmd = cmd;

		/* if requested, identify ourselves */
		if (strcmp(drvname, "?dhd") == 0) {
			sprintf(info.driver, "dhd");
			strcpy(info.version, BRCMF_VERSION_STR);
		}
448
		/* report dongle driver type */
449
		else
450
			sprintf(info.driver, "wl");
451

452
		sprintf(info.version, "%lu", drvr->drv_version);
453 454
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
455
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
456 457 458 459 460 461
			  (int)sizeof(drvname), drvname, info.driver);
		break;

		/* Get toe offload components from dongle */
	case ETHTOOL_GRXCSUM:
	case ETHTOOL_GTXCSUM:
462
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
		if (ret < 0)
			return ret;

		csum_dir =
		    (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;

		edata.cmd = cmd;
		edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;

		if (copy_to_user(uaddr, &edata, sizeof(edata)))
			return -EFAULT;
		break;

		/* Set toe offload components in dongle */
	case ETHTOOL_SRXCSUM:
	case ETHTOOL_STXCSUM:
		if (copy_from_user(&edata, uaddr, sizeof(edata)))
			return -EFAULT;

		/* Read the current settings, update and write back */
483
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
484 485 486 487 488 489 490 491 492 493 494
		if (ret < 0)
			return ret;

		csum_dir =
		    (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;

		if (edata.data != 0)
			toe_cmpnt |= csum_dir;
		else
			toe_cmpnt &= ~csum_dir;

495
		ret = brcmf_toe_set(ifp, toe_cmpnt);
496 497 498 499 500 501
		if (ret < 0)
			return ret;

		/* If setting TX checksum mode, tell Linux the new mode */
		if (cmd == ETHTOOL_STXCSUM) {
			if (edata.data)
502
				ifp->ndev->features |= NETIF_F_IP_CSUM;
503
			else
504
				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
505 506 507 508 509 510 511 512 513 514 515 516 517 518
		}

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
519
	struct brcmf_if *ifp = netdev_priv(ndev);
520
	struct brcmf_pub *drvr = ifp->drvr;
521

522
	brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
523

524
	if (!drvr->iflist[ifp->idx])
525 526 527
		return -1;

	if (cmd == SIOCETHTOOL)
528
		return brcmf_ethtool(ifp, ifr->ifr_data);
529 530 531 532 533 534 535

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
	brcmf_dbg(TRACE, "Enter\n");
536

537
	brcmf_cfg80211_down(ndev);
538

539 540 541 542 543 544 545 546
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
547
	struct brcmf_if *ifp = netdev_priv(ndev);
548
	struct brcmf_pub *drvr = ifp->drvr;
549
	struct brcmf_bus *bus_if = drvr->bus_if;
550 551 552
	u32 toe_ol;
	s32 ret = 0;

553
	brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
554

555 556
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
557
		brcmf_err("failed bus is not ready\n");
558 559
		return -EAGAIN;
	}
560

561
	atomic_set(&ifp->pend_8021x_cnt, 0);
562

563 564 565
	/* Get current TOE mode from dongle */
	if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
	    && (toe_ol & TOE_TX_CSUM_OL) != 0)
566
		ndev->features |= NETIF_F_IP_CSUM;
567
	else
568
		ndev->features &= ~NETIF_F_IP_CSUM;
569

570 571
	/* Allow transmit calls */
	netif_start_queue(ndev);
572
	if (brcmf_cfg80211_up(ndev)) {
573
		brcmf_err("failed to bring up cfg80211\n");
574 575 576 577 578 579
		return -1;
	}

	return ret;
}

580 581 582 583 584 585 586 587 588 589
static const struct net_device_ops brcmf_netdev_ops_pri = {
	.ndo_open = brcmf_netdev_open,
	.ndo_stop = brcmf_netdev_stop,
	.ndo_get_stats = brcmf_netdev_get_stats,
	.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
	.ndo_start_xmit = brcmf_netdev_start_xmit,
	.ndo_set_mac_address = brcmf_netdev_set_mac_address,
	.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};

590 591 592 593 594 595 596 597 598 599
static const struct net_device_ops brcmf_netdev_ops_virt = {
	.ndo_open = brcmf_cfg80211_up,
	.ndo_stop = brcmf_cfg80211_down,
	.ndo_get_stats = brcmf_netdev_get_stats,
	.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
	.ndo_start_xmit = brcmf_netdev_start_xmit,
	.ndo_set_mac_address = brcmf_netdev_set_mac_address,
	.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};

600
int brcmf_net_attach(struct brcmf_if *ifp)
601
{
602
	struct brcmf_pub *drvr = ifp->drvr;
603 604
	struct net_device *ndev;

605 606
	brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
	ndev = ifp->ndev;
607

608 609 610 611 612
	/* set appropriate operations */
	if (!ifp->idx)
		ndev->netdev_ops = &brcmf_netdev_ops_pri;
	else
		ndev->netdev_ops = &brcmf_netdev_ops_virt;
613 614 615 616 617 618 619

	ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
	ndev->ethtool_ops = &brcmf_ethtool_ops;

	drvr->rxsz = ndev->mtu + ndev->hard_header_len +
			      drvr->hdrlen;

620 621
	/* set the mac address */
	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
622 623

	if (register_netdev(ndev) != 0) {
624
		brcmf_err("couldn't register the net device\n");
625 626 627 628 629 630 631 632 633 634 635 636
		goto fail;
	}

	brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);

	return 0;

fail:
	ndev->netdev_ops = NULL;
	return -EBADE;
}

637
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
638
			      char *name, u8 *addr_mask)
639 640
{
	struct brcmf_if *ifp;
641
	struct net_device *ndev;
642
	int i;
643

644
	brcmf_dbg(TRACE, "idx %d\n", ifidx);
645

646
	ifp = drvr->iflist[ifidx];
647 648 649 650 651
	/*
	 * Delete the existing interface before overwriting it
	 * in case we missed the BRCMF_E_IF_DEL event.
	 */
	if (ifp) {
652
		brcmf_err("ERROR: netdev:%s already exists\n",
653
			  ifp->ndev->name);
654 655 656 657 658 659
		if (ifidx) {
			netif_stop_queue(ifp->ndev);
			unregister_netdev(ifp->ndev);
			free_netdev(ifp->ndev);
			drvr->iflist[ifidx] = NULL;
		} else {
660
			brcmf_err("ignore IF event\n");
661 662
			return ERR_PTR(-EINVAL);
		}
663
	}
664

665
	/* Allocate netdev, including space for private structure */
666 667
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
668
		brcmf_err("OOM - alloc_netdev\n");
669
		return ERR_PTR(-ENOMEM);
670
	}
671

672 673
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
674 675
	ifp->drvr = drvr;
	drvr->iflist[ifidx] = ifp;
676
	ifp->idx = ifidx;
677
	ifp->bssidx = bssidx;
678 679 680 681

	INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);

682 683
	init_waitqueue_head(&ifp->pend_8021x_wait);

684 685 686
	if (addr_mask != NULL)
		for (i = 0; i < ETH_ALEN; i++)
			ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
687

688 689
	brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
		  current->pid, ifp->ndev->name, ifp->mac_addr);
690

691
	return ifp;
692 693
}

694
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
695 696 697 698 699
{
	struct brcmf_if *ifp;

	brcmf_dbg(TRACE, "idx %d\n", ifidx);

700
	ifp = drvr->iflist[ifidx];
701
	if (!ifp) {
702
		brcmf_err("Null interface\n");
703 704
		return;
	}
705 706 707 708 709 710 711 712 713 714 715
	if (ifp->ndev) {
		if (ifidx == 0) {
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

716 717 718
		cancel_work_sync(&ifp->setmacaddr_work);
		cancel_work_sync(&ifp->multicast_work);

719
		unregister_netdev(ifp->ndev);
720
		drvr->iflist[ifidx] = NULL;
721
		if (ifidx == 0)
722
			brcmf_cfg80211_detach(drvr->config);
723
		free_netdev(ifp->ndev);
724 725 726
	}
}

727
int brcmf_attach(uint bus_hdrlen, struct device *dev)
728
{
729
	struct brcmf_pub *drvr = NULL;
730
	int ret = 0;
731 732 733 734

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
735 736
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
737
		return -ENOMEM;
738

739
	mutex_init(&drvr->proto_block);
740 741

	/* Link to bus module */
742 743
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
744
	drvr->bus_if->drvr = drvr;
745

746 747 748
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

749
	/* Attach and link in the protocol */
750 751
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
752
		brcmf_err("brcmf_prot_attach failed\n");
753 754 755
		goto fail;
	}

756 757 758
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

759 760
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

761
	return ret;
762 763

fail:
764
	brcmf_detach(dev);
765

766
	return ret;
767 768
}

769
int brcmf_bus_start(struct device *dev)
770 771
{
	int ret = -1;
772 773
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
774
	struct brcmf_if *ifp;
775 776 777 778

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
779
	ret = brcmf_bus_init(bus_if);
780
	if (ret != 0) {
781
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
782 783 784
		return ret;
	}

785
	/* add primary networking interface */
786
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
787 788 789
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

790 791 792 793 794
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
795
	if (ret < 0)
796
		goto fail;
797

A
Arend van Spriel 已提交
798
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
799 800 801 802
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
803

804 805 806 807
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

808
	ret = brcmf_net_attach(ifp);
809
fail:
810
	if (ret < 0) {
811
		brcmf_err("failed: %d\n", ret);
812 813 814
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
		free_netdev(drvr->iflist[0]->ndev);
815
		drvr->iflist[0] = NULL;
816
		return ret;
817 818
	}

819 820 821 822 823 824 825 826
	return 0;
}

static void brcmf_bus_detach(struct brcmf_pub *drvr)
{
	brcmf_dbg(TRACE, "Enter\n");

	if (drvr) {
827 828
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
829

830
		/* Stop the bus module */
A
Arend van Spriel 已提交
831
		brcmf_bus_stop(drvr->bus_if);
832 833 834
	}
}

835 836 837 838 839 840 841 842 843 844 845
void brcmf_dev_reset(struct device *dev)
{
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;

	if (drvr == NULL)
		return;

	brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
}

846
void brcmf_detach(struct device *dev)
847
{
848 849 850
	int i;
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
851 852 853

	brcmf_dbg(TRACE, "Enter\n");

854 855
	if (drvr == NULL)
		return;
856

857 858 859
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

860 861 862 863
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
		if (drvr->iflist[i])
			brcmf_del_if(drvr, i);
864

865
	brcmf_bus_detach(drvr);
866

867
	if (drvr->prot)
868
		brcmf_proto_detach(drvr);
869

870
	brcmf_debugfs_detach(drvr);
871 872
	bus_if->drvr = NULL;
	kfree(drvr);
873 874
}

875
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
876
{
877
	return atomic_read(&ifp->pend_8021x_cnt);
878 879 880 881
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
882
	struct brcmf_if *ifp = netdev_priv(ndev);
883 884
	int err;

885 886
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
887 888 889 890 891
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
892 893
}

894
static void brcmf_driver_init(struct work_struct *work)
895
{
896 897
	brcmf_debugfs_init();

898
#ifdef CONFIG_BRCMFMAC_SDIO
899
	brcmf_sdio_init();
900
#endif
901
#ifdef CONFIG_BRCMFMAC_USB
902
	brcmf_usb_init();
903
#endif
904 905 906 907 908 909 910 911
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

static int __init brcmfmac_module_init(void)
{
	if (!schedule_work(&brcmf_driver_work))
		return -EBUSY;

912
	return 0;
913 914
}

915
static void __exit brcmfmac_module_exit(void)
916
{
917 918
	cancel_work_sync(&brcmf_driver_work);

919 920 921
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
922 923 924
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
925
	brcmf_debugfs_exit();
926 927
}

928 929
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);