dhd_linux.c 23.9 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
#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"
29
#include "fwil_types.h"
30
#include "p2p.h"
31
#include "wl_cfg80211.h"
32
#include "fwil.h"
33
#include "fwsignal.h"
34 35

MODULE_AUTHOR("Broadcom Corporation");
H
Hante Meuleman 已提交
36
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
37 38
MODULE_LICENSE("Dual BSD/GPL");

39
#define MAX_WAIT_FOR_8021X_TX		50	/* msecs */
40 41

/* Error bits */
42
int brcmf_msg_level;
43 44
module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(debug, "level of debug output");
45

46 47 48 49 50 51
/* P2P0 enable */
static int brcmf_p2p_enable;
#ifdef CONFIG_BRCMDBG
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
#endif
52 53 54 55

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

60
	if (drvr->iflist[ifidx] == NULL) {
61
		brcmf_err("null i/f %d\n", ifidx);
62 63 64
		return "<if_null>";
	}

65 66
	if (drvr->iflist[ifidx]->ndev)
		return drvr->iflist[ifidx]->ndev->name;
67 68 69 70 71 72

	return "<if_none>";
}

static void _brcmf_set_multicast_list(struct work_struct *work)
{
73
	struct brcmf_if *ifp;
74 75
	struct net_device *ndev;
	struct netdev_hw_addr *ha;
76
	u32 cmd_value, cnt;
77 78
	__le32 cnt_le;
	char *buf, *bufp;
79 80
	u32 buflen;
	s32 err;
81

82
	ifp = container_of(work, struct brcmf_if, multicast_work);
83

84
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
85

86
	ndev = ifp->ndev;
87 88

	/* Determine initial value of allmulti flag */
89
	cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
90 91

	/* Send down the multicast list first. */
92 93 94 95
	cnt = netdev_mc_count(ndev);
	buflen = sizeof(cnt) + (cnt * ETH_ALEN);
	buf = kmalloc(buflen, GFP_ATOMIC);
	if (!buf)
96
		return;
97
	bufp = buf;
98 99

	cnt_le = cpu_to_le32(cnt);
100
	memcpy(bufp, &cnt_le, sizeof(cnt_le));
101 102 103 104 105 106 107 108 109 110
	bufp += sizeof(cnt_le);

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

111 112
	err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
	if (err < 0) {
113
		brcmf_err("Setting mcast_list failed, %d\n", err);
114
		cmd_value = cnt ? true : cmd_value;
115 116 117 118
	}

	kfree(buf);

119 120
	/*
	 * Now send the allmulti setting.  This is based on the setting in the
121 122 123
	 * net_device flags, but might be modified above to be turned on if we
	 * were trying to set some addresses and dongle rejected it...
	 */
124 125
	err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
	if (err < 0)
126
		brcmf_err("Setting allmulti failed, %d\n", err);
127 128 129 130 131

	/*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)
132
		brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
133
			  err);
134 135 136 137 138
}

static void
_brcmf_set_mac_address(struct work_struct *work)
{
139 140
	struct brcmf_if *ifp;
	s32 err;
141

142
	ifp = container_of(work, struct brcmf_if, setmacaddr_work);
143

144
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
145

146
	err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
147 148
				       ETH_ALEN);
	if (err < 0) {
149
		brcmf_err("Setting cur_etheraddr failed, %d\n", err);
150 151
	} else {
		brcmf_dbg(TRACE, "MAC address updated to %pM\n",
152 153
			  ifp->mac_addr);
		memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
154
	}
155 156 157 158
}

static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{
159
	struct brcmf_if *ifp = netdev_priv(ndev);
160 161
	struct sockaddr *sa = (struct sockaddr *)addr;

162 163
	memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
	schedule_work(&ifp->setmacaddr_work);
164 165 166 167 168
	return 0;
}

static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{
169
	struct brcmf_if *ifp = netdev_priv(ndev);
170

171
	schedule_work(&ifp->multicast_work);
172 173
}

174 175
static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
					   struct net_device *ndev)
176 177
{
	int ret;
178
	struct brcmf_if *ifp = netdev_priv(ndev);
179
	struct brcmf_pub *drvr = ifp->drvr;
180
	struct ethhdr *eh;
181

182
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
183

184 185 186
	/* Can the device send data? */
	if (drvr->bus_if->state != BRCMF_BUS_DATA) {
		brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
187
		netif_stop_queue(ndev);
188 189 190
		dev_kfree_skb(skb);
		ret = -ENODEV;
		goto done;
191 192
	}

193 194
	if (!drvr->iflist[ifp->bssidx]) {
		brcmf_err("bad ifidx %d\n", ifp->bssidx);
195
		netif_stop_queue(ndev);
196 197 198
		dev_kfree_skb(skb);
		ret = -ENODEV;
		goto done;
199 200 201
	}

	/* Make sure there's enough room for any header */
202
	if (skb_headroom(skb) < drvr->hdrlen) {
203 204 205
		struct sk_buff *skb2;

		brcmf_dbg(INFO, "%s: insufficient headroom\n",
206
			  brcmf_ifname(drvr, ifp->bssidx));
207
		drvr->bus_if->tx_realloc++;
208
		skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
209 210 211
		dev_kfree_skb(skb);
		skb = skb2;
		if (skb == NULL) {
212
			brcmf_err("%s: skb_realloc_headroom failed\n",
213
				  brcmf_ifname(drvr, ifp->bssidx));
214 215 216 217 218
			ret = -ENOMEM;
			goto done;
		}
	}

219 220 221 222 223
	/* validate length for ether packet */
	if (skb->len < sizeof(*eh)) {
		ret = -EINVAL;
		dev_kfree_skb(skb);
		goto done;
224 225
	}

226
	ret = brcmf_fws_process_skb(ifp, 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 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
void brcmf_txflowblock_if(struct brcmf_if *ifp,
			  enum brcmf_netif_stop_reason reason, bool state)
{
	if (!ifp)
		return;

	brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
		  ifp->bssidx, ifp->netif_stop, reason, state);
	if (state) {
		if (!ifp->netif_stop)
			netif_stop_queue(ifp->ndev);
		ifp->netif_stop |= reason;
	} else {
		ifp->netif_stop &= ~reason;
		if (!ifp->netif_stop)
			netif_wake_queue(ifp->ndev);
	}
}

259
void brcmf_txflowblock(struct device *dev, bool state)
260
{
261 262
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
263
	int i;
264 265 266

	brcmf_dbg(TRACE, "Enter\n");

267
	for (i = 0; i < BRCMF_MAX_IFS; i++)
268 269
		brcmf_txflowblock_if(drvr->iflist[i],
				     BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
270 271
}

272
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
273 274 275
{
	unsigned char *eth;
	uint len;
276
	struct sk_buff *skb, *pnext;
277
	struct brcmf_if *ifp;
278 279
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
280 281
	u8 ifidx;
	int ret;
282 283 284

	brcmf_dbg(TRACE, "Enter\n");

285 286
	skb_queue_walk_safe(skb_list, skb, pnext) {
		skb_unlink(skb, skb_list);
287

288
		/* process and remove protocol-specific header */
289
		ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb);
290 291 292 293 294
		ifp = drvr->iflist[ifidx];

		if (ret || !ifp || !ifp->ndev) {
			if ((ret != -ENODATA) && ifp)
				ifp->stats.rx_errors++;
295 296 297 298
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
		/* 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)
318
			ifp->stats.multicast++;
319 320 321 322 323 324 325 326

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

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

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

329 330
		if (drvr->iflist[ifidx]) {
			ifp = drvr->iflist[ifidx];
331
			ifp->ndev->last_rx = jiffies;
332
		}
333

334 335 336 337 338 339 340
		if (!(ifp->ndev->flags & IFF_UP)) {
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

		ifp->stats.rx_bytes += skb->len;
		ifp->stats.rx_packets++;
341 342 343 344 345 346 347 348 349 350 351 352 353 354

		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);
	}
}

355 356
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
		      bool success)
357
{
358
	struct brcmf_if *ifp;
359
	struct ethhdr *eh;
360
	u8 ifidx;
361
	u16 type;
362
	int res;
363

364
	res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
365

366 367
	ifp = drvr->iflist[ifidx];
	if (!ifp)
368
		goto done;
369

370 371 372
	if (res == 0) {
		eh = (struct ethhdr *)(txp->data);
		type = ntohs(eh->h_proto);
373

374 375 376 377 378
		if (type == ETH_P_PAE) {
			atomic_dec(&ifp->pend_8021x_cnt);
			if (waitqueue_active(&ifp->pend_8021x_wait))
				wake_up(&ifp->pend_8021x_wait);
		}
379
	}
380 381
	if (!success)
		ifp->stats.tx_errors++;
382 383
done:
	brcmu_pkt_buf_free_skb(txp);
384
}
385

386 387 388 389 390
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;

391 392 393 394 395 396 397
	/* await txstatus signal for firmware if active */
	if (brcmf_fws_fc_active(drvr->fws)) {
		if (!success)
			brcmf_fws_bustxfail(drvr->fws, txp);
	} else {
		brcmf_txfinalize(drvr, txp, success);
	}
398 399 400 401
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
402
	struct brcmf_if *ifp = netdev_priv(ndev);
403

404
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
405 406 407 408

	return &ifp->stats;
}

409 410 411 412 413
/*
 * 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)
414
{
415
	s32 err;
416

417 418
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
419
		brcmf_err("Setting toe_ol failed, %d\n", err);
420
		return err;
421 422
	}

423 424
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
425
		brcmf_err("Setting toe failed, %d\n", err);
426

427
	return err;
428 429 430 431 432 433

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
434
	struct brcmf_if *ifp = netdev_priv(ndev);
435
	struct brcmf_pub *drvr = ifp->drvr;
436

437 438 439 440 441
	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
	snprintf(info->version, sizeof(info->version), "%lu",
		 drvr->drv_version);
	strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
		sizeof(info->bus_info));
442 443
}

444 445
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
446 447
};

448
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
449
{
450
	struct brcmf_pub *drvr = ifp->drvr;
451 452 453 454 455 456 457
	struct ethtool_drvinfo info;
	char drvname[sizeof(info.driver)];
	u32 cmd;
	struct ethtool_value edata;
	u32 toe_cmpnt, csum_dir;
	int ret;

458
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

	/* 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);
		}
481
		/* report dongle driver type */
482
		else
483
			sprintf(info.driver, "wl");
484

485
		sprintf(info.version, "%lu", drvr->drv_version);
486 487
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
488
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
489 490 491 492 493 494
			  (int)sizeof(drvname), drvname, info.driver);
		break;

		/* Get toe offload components from dongle */
	case ETHTOOL_GRXCSUM:
	case ETHTOOL_GTXCSUM:
495
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
		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 */
516
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
517 518 519 520 521 522 523 524 525 526 527
		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;

528
		ret = brcmf_toe_set(ifp, toe_cmpnt);
529 530 531 532 533 534
		if (ret < 0)
			return ret;

		/* If setting TX checksum mode, tell Linux the new mode */
		if (cmd == ETHTOOL_STXCSUM) {
			if (edata.data)
535
				ifp->ndev->features |= NETIF_F_IP_CSUM;
536
			else
537
				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
538 539 540 541 542 543 544 545 546 547 548 549 550 551
		}

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
552
	struct brcmf_if *ifp = netdev_priv(ndev);
553
	struct brcmf_pub *drvr = ifp->drvr;
554

555
	brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
556

557
	if (!drvr->iflist[ifp->bssidx])
558 559 560
		return -1;

	if (cmd == SIOCETHTOOL)
561
		return brcmf_ethtool(ifp, ifr->ifr_data);
562 563 564 565 566 567

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
568
	struct brcmf_if *ifp = netdev_priv(ndev);
569

570
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
571

572
	brcmf_cfg80211_down(ndev);
573

574 575 576 577 578 579 580 581
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
582
	struct brcmf_if *ifp = netdev_priv(ndev);
583
	struct brcmf_pub *drvr = ifp->drvr;
584
	struct brcmf_bus *bus_if = drvr->bus_if;
585 586 587
	u32 toe_ol;
	s32 ret = 0;

588
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
589

590 591
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
592
		brcmf_err("failed bus is not ready\n");
593 594
		return -EAGAIN;
	}
595

596
	atomic_set(&ifp->pend_8021x_cnt, 0);
597

598 599 600
	/* 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)
601
		ndev->features |= NETIF_F_IP_CSUM;
602
	else
603
		ndev->features &= ~NETIF_F_IP_CSUM;
604

605 606
	/* Allow transmit calls */
	netif_start_queue(ndev);
607
	if (brcmf_cfg80211_up(ndev)) {
608
		brcmf_err("failed to bring up cfg80211\n");
609 610 611 612 613 614
		return -1;
	}

	return ret;
}

615 616 617 618 619 620 621 622 623 624
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
};

625
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
626
{
627
	struct brcmf_pub *drvr = ifp->drvr;
628
	struct net_device *ndev;
629
	s32 err;
630

631
	brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
632
		  ifp->mac_addr);
633
	ndev = ifp->ndev;
634

635
	/* set appropriate operations */
636
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
637 638 639 640 641 642 643

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

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

644 645
	/* set the mac address */
	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
646

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

650 651 652 653 654
	if (rtnl_locked)
		err = register_netdevice(ndev);
	else
		err = register_netdev(ndev);
	if (err != 0) {
655
		brcmf_err("couldn't register the net device\n");
656 657 658 659 660 661 662 663 664 665 666 667
		goto fail;
	}

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

	return 0;

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

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
static int brcmf_net_p2p_open(struct net_device *ndev)
{
	brcmf_dbg(TRACE, "Enter\n");

	return brcmf_cfg80211_up(ndev);
}

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

	return brcmf_cfg80211_down(ndev);
}

static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
				  struct ifreq *ifr, int cmd)
{
	brcmf_dbg(TRACE, "Enter\n");
	return 0;
}

static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
					    struct net_device *ndev)
{
	if (skb)
		dev_kfree_skb_any(skb);

	return NETDEV_TX_OK;
}

static const struct net_device_ops brcmf_netdev_ops_p2p = {
	.ndo_open = brcmf_net_p2p_open,
	.ndo_stop = brcmf_net_p2p_stop,
	.ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
	.ndo_start_xmit = brcmf_net_p2p_start_xmit
};

static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
{
	struct net_device *ndev;

	brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
		  ifp->mac_addr);
	ndev = ifp->ndev;

	ndev->netdev_ops = &brcmf_netdev_ops_p2p;

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

	if (register_netdev(ndev) != 0) {
		brcmf_err("couldn't register the p2p net device\n");
		goto fail;
	}

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

	return 0;

fail:
	return -EBADE;
}

731 732
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
733 734
{
	struct brcmf_if *ifp;
735
	struct net_device *ndev;
736

737
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
738

739
	ifp = drvr->iflist[bssidx];
740 741 742 743 744
	/*
	 * Delete the existing interface before overwriting it
	 * in case we missed the BRCMF_E_IF_DEL event.
	 */
	if (ifp) {
745
		brcmf_err("ERROR: netdev:%s already exists\n",
746
			  ifp->ndev->name);
747 748 749 750
		if (ifidx) {
			netif_stop_queue(ifp->ndev);
			unregister_netdev(ifp->ndev);
			free_netdev(ifp->ndev);
751
			drvr->iflist[bssidx] = NULL;
752
		} else {
753
			brcmf_err("ignore IF event\n");
754 755
			return ERR_PTR(-EINVAL);
		}
756
	}
757

758
	/* Allocate netdev, including space for private structure */
759 760
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
761
		brcmf_err("OOM - alloc_netdev\n");
762
		return ERR_PTR(-ENOMEM);
763
	}
764

765 766
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
767
	ifp->drvr = drvr;
768 769
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
770
	ifp->bssidx = bssidx;
771

772 773
	init_waitqueue_head(&ifp->pend_8021x_wait);

774 775
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
776

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

780
	return ifp;
781 782
}

783
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
784 785 786
{
	struct brcmf_if *ifp;

787
	ifp = drvr->iflist[bssidx];
788
	if (!ifp) {
789
		brcmf_err("Null interface, idx=%d\n", bssidx);
790 791
		return;
	}
792
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
793
	if (ifp->ndev) {
794
		if (bssidx == 0) {
795 796 797 798 799 800 801 802 803
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

804 805 806 807
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
808

809
		unregister_netdev(ifp->ndev);
810 811
		drvr->iflist[bssidx] = NULL;
		if (bssidx == 0)
812
			brcmf_cfg80211_detach(drvr->config);
813
		free_netdev(ifp->ndev);
814 815 816
	}
}

817
int brcmf_attach(uint bus_hdrlen, struct device *dev)
818
{
819
	struct brcmf_pub *drvr = NULL;
820
	int ret = 0;
821 822 823 824

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
825 826
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
827
		return -ENOMEM;
828

829
	mutex_init(&drvr->proto_block);
830 831

	/* Link to bus module */
832 833
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
834
	drvr->bus_if->drvr = drvr;
835

836 837 838
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

839
	/* Attach and link in the protocol */
840 841
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
842
		brcmf_err("brcmf_prot_attach failed\n");
843 844 845
		goto fail;
	}

846 847 848
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

849 850
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

851
	return ret;
852 853

fail:
854
	brcmf_detach(dev);
855

856
	return ret;
857 858
}

859
int brcmf_bus_start(struct device *dev)
860 861
{
	int ret = -1;
862 863
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
864
	struct brcmf_if *ifp;
865
	struct brcmf_if *p2p_ifp;
866 867 868 869

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
870
	ret = brcmf_bus_init(bus_if);
871
	if (ret != 0) {
872
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
873 874 875
		return ret;
	}

876
	/* add primary networking interface */
877
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
878 879 880
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

881 882 883 884 885 886 887
	if (brcmf_p2p_enable)
		p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
	else
		p2p_ifp = NULL;
	if (IS_ERR(p2p_ifp))
		p2p_ifp = NULL;

888 889 890 891 892
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
893
	if (ret < 0)
894
		goto fail;
895

896 897
	drvr->fw_signals = true;
	(void)brcmf_fws_init(drvr);
898
	brcmf_fws_add_interface(ifp);
899

A
Arend van Spriel 已提交
900
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
901 902 903 904
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
905

906 907 908 909
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

910
	ret = brcmf_net_attach(ifp, false);
911
fail:
912
	if (ret < 0) {
913
		brcmf_err("failed: %d\n", ret);
914 915
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
916 917
		if (drvr->fws) {
			brcmf_fws_del_interface(ifp);
918
			brcmf_fws_deinit(drvr);
919
		}
920
		free_netdev(ifp->ndev);
921
		drvr->iflist[0] = NULL;
922 923 924 925
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
926
		return ret;
927
	}
928 929
	if ((brcmf_p2p_enable) && (p2p_ifp))
		brcmf_net_p2p_attach(p2p_ifp);
930

931 932 933 934 935 936 937 938
	return 0;
}

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

	if (drvr) {
939 940
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
941

942
		/* Stop the bus module */
A
Arend van Spriel 已提交
943
		brcmf_bus_stop(drvr->bus_if);
944 945 946
	}
}

947 948 949 950 951 952 953 954
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;

955 956
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
957 958
}

959
void brcmf_detach(struct device *dev)
960
{
961
	s32 i;
962 963
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
964 965 966

	brcmf_dbg(TRACE, "Enter\n");

967 968
	if (drvr == NULL)
		return;
969

970 971 972
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

973 974
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
975 976
		if (drvr->iflist[i]) {
			brcmf_fws_del_interface(drvr->iflist[i]);
977
			brcmf_del_if(drvr, i);
978
		}
979

980
	brcmf_bus_detach(drvr);
981

982
	if (drvr->prot)
983
		brcmf_proto_detach(drvr);
984

985
	brcmf_fws_deinit(drvr);
986

987
	brcmf_debugfs_detach(drvr);
988 989
	bus_if->drvr = NULL;
	kfree(drvr);
990 991
}

992
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
993
{
994
	return atomic_read(&ifp->pend_8021x_cnt);
995 996 997 998
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
999
	struct brcmf_if *ifp = netdev_priv(ndev);
1000 1001
	int err;

1002 1003
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
1004 1005 1006 1007 1008
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
1009 1010
}

1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
/*
 * return chip id and rev of the device encoded in u32.
 */
u32 brcmf_get_chip_info(struct brcmf_if *ifp)
{
	struct brcmf_bus *bus = ifp->drvr->bus_if;

	return bus->chip << 4 | bus->chiprev;
}

1021
static void brcmf_driver_init(struct work_struct *work)
1022
{
1023 1024
	brcmf_debugfs_init();

1025
#ifdef CONFIG_BRCMFMAC_SDIO
1026
	brcmf_sdio_init();
1027
#endif
1028
#ifdef CONFIG_BRCMFMAC_USB
1029
	brcmf_usb_init();
1030
#endif
1031 1032 1033 1034 1035 1036 1037 1038
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

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

1039
	return 0;
1040 1041
}

1042
static void __exit brcmfmac_module_exit(void)
1043
{
1044 1045
	cancel_work_sync(&brcmf_driver_work);

1046 1047 1048
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1049 1050 1051
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1052
	brcmf_debugfs_exit();
1053 1054
}

1055 1056
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);