dhd_linux.c 23.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
#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 34

MODULE_AUTHOR("Broadcom Corporation");
H
Hante Meuleman 已提交
35 36
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
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(brcmf_msg_level, int, 0);

45 46 47 48 49 50
/* 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
51 52 53 54

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

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

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

	return "<if_none>";
}

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

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

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

85
	ndev = ifp->ndev;
86 87

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

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

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

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

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

	kfree(buf);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

225 226 227 228 229
	/* 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)
230
		atomic_inc(&ifp->pend_8021x_cnt);
231

232
	/* If the protocol uses a data header, apply it */
233
	brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
234 235

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

done:
239 240 241 242 243 244
	if (ret) {
		ifp->stats.tx_dropped++;
	} else {
		ifp->stats.tx_packets++;
		ifp->stats.tx_bytes += skb->len;
	}
245 246

	/* Return ok: we always eat the packet */
247
	return NETDEV_TX_OK;
248 249
}

250
void brcmf_txflowblock(struct device *dev, bool state)
251 252
{
	struct net_device *ndev;
253 254
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
255
	int i;
256 257 258

	brcmf_dbg(TRACE, "Enter\n");

259 260 261 262 263 264 265 266
	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);
		}
267 268
}

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

	brcmf_dbg(TRACE, "Enter\n");

282 283
	skb_queue_walk_safe(skb_list, skb, pnext) {
		skb_unlink(skb, skb_list);
284

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

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

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

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

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

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

326 327
		if (drvr->iflist[ifidx]) {
			ifp = drvr->iflist[ifidx];
328
			ifp->ndev->last_rx = jiffies;
329
		}
330

331 332 333 334 335 336 337
		if (!(ifp->ndev->flags & IFF_UP)) {
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

		ifp->stats.rx_bytes += skb->len;
		ifp->stats.rx_packets++;
338 339 340 341 342 343 344 345 346 347 348 349 350 351

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

352
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
353
{
354
	u8 ifidx;
355 356
	struct ethhdr *eh;
	u16 type;
357 358
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
359
	struct brcmf_if *ifp;
360

361
	brcmf_proto_hdrpull(drvr, &ifidx, txp);
362

363 364 365 366
	ifp = drvr->iflist[ifidx];
	if (!ifp)
		return;

367 368 369
	eh = (struct ethhdr *)(txp->data);
	type = ntohs(eh->h_proto);

370
	if (type == ETH_P_PAE) {
371 372 373
		atomic_dec(&ifp->pend_8021x_cnt);
		if (waitqueue_active(&ifp->pend_8021x_wait))
			wake_up(&ifp->pend_8021x_wait);
374
	}
375 376
	if (!success)
		ifp->stats.tx_errors++;
377 378 379 380
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
381
	struct brcmf_if *ifp = netdev_priv(ndev);
382

383
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
384 385 386 387

	return &ifp->stats;
}

388 389 390 391 392
/*
 * 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)
393
{
394
	s32 err;
395

396 397
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
398
		brcmf_err("Setting toe_ol failed, %d\n", err);
399
		return err;
400 401
	}

402 403
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
404
		brcmf_err("Setting toe failed, %d\n", err);
405

406
	return err;
407 408 409 410 411 412

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
413
	struct brcmf_if *ifp = netdev_priv(ndev);
414
	struct brcmf_pub *drvr = ifp->drvr;
415

416 417 418 419 420
	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));
421 422
}

423 424
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
425 426
};

427
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
428
{
429
	struct brcmf_pub *drvr = ifp->drvr;
430 431 432 433 434 435 436
	struct ethtool_drvinfo info;
	char drvname[sizeof(info.driver)];
	u32 cmd;
	struct ethtool_value edata;
	u32 toe_cmpnt, csum_dir;
	int ret;

437
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459

	/* 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);
		}
460
		/* report dongle driver type */
461
		else
462
			sprintf(info.driver, "wl");
463

464
		sprintf(info.version, "%lu", drvr->drv_version);
465 466
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
467
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
468 469 470 471 472 473
			  (int)sizeof(drvname), drvname, info.driver);
		break;

		/* Get toe offload components from dongle */
	case ETHTOOL_GRXCSUM:
	case ETHTOOL_GTXCSUM:
474
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
		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 */
495
		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
496 497 498 499 500 501 502 503 504 505 506
		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;

507
		ret = brcmf_toe_set(ifp, toe_cmpnt);
508 509 510 511 512 513
		if (ret < 0)
			return ret;

		/* If setting TX checksum mode, tell Linux the new mode */
		if (cmd == ETHTOOL_STXCSUM) {
			if (edata.data)
514
				ifp->ndev->features |= NETIF_F_IP_CSUM;
515
			else
516
				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
517 518 519 520 521 522 523 524 525 526 527 528 529 530
		}

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
531
	struct brcmf_if *ifp = netdev_priv(ndev);
532
	struct brcmf_pub *drvr = ifp->drvr;
533

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

536
	if (!drvr->iflist[ifp->bssidx])
537 538 539
		return -1;

	if (cmd == SIOCETHTOOL)
540
		return brcmf_ethtool(ifp, ifr->ifr_data);
541 542 543 544 545 546

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
547
	struct brcmf_if *ifp = netdev_priv(ndev);
548

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

551
	brcmf_cfg80211_down(ndev);
552

553 554 555 556 557 558 559 560
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
561
	struct brcmf_if *ifp = netdev_priv(ndev);
562
	struct brcmf_pub *drvr = ifp->drvr;
563
	struct brcmf_bus *bus_if = drvr->bus_if;
564 565 566
	u32 toe_ol;
	s32 ret = 0;

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

569 570
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
571
		brcmf_err("failed bus is not ready\n");
572 573
		return -EAGAIN;
	}
574

575
	atomic_set(&ifp->pend_8021x_cnt, 0);
576

577 578 579
	/* 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)
580
		ndev->features |= NETIF_F_IP_CSUM;
581
	else
582
		ndev->features &= ~NETIF_F_IP_CSUM;
583

584 585
	/* Allow transmit calls */
	netif_start_queue(ndev);
586
	if (brcmf_cfg80211_up(ndev)) {
587
		brcmf_err("failed to bring up cfg80211\n");
588 589 590 591 592 593
		return -1;
	}

	return ret;
}

594 595 596 597 598 599 600 601 602 603
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
};

604
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
605
{
606
	struct brcmf_pub *drvr = ifp->drvr;
607
	struct net_device *ndev;
608
	s32 err;
609

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

614
	/* set appropriate operations */
615
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
616 617 618 619 620 621 622

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

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

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

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

629 630 631 632 633
	if (rtnl_locked)
		err = register_netdevice(ndev);
	else
		err = register_netdev(ndev);
	if (err != 0) {
634
		brcmf_err("couldn't register the net device\n");
635 636 637 638 639 640 641 642 643 644 645 646
		goto fail;
	}

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

	return 0;

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

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 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
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;
}

710 711
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
712 713
{
	struct brcmf_if *ifp;
714
	struct net_device *ndev;
715

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

718
	ifp = drvr->iflist[bssidx];
719 720 721 722 723
	/*
	 * Delete the existing interface before overwriting it
	 * in case we missed the BRCMF_E_IF_DEL event.
	 */
	if (ifp) {
724
		brcmf_err("ERROR: netdev:%s already exists\n",
725
			  ifp->ndev->name);
726 727 728 729
		if (ifidx) {
			netif_stop_queue(ifp->ndev);
			unregister_netdev(ifp->ndev);
			free_netdev(ifp->ndev);
730
			drvr->iflist[bssidx] = NULL;
731
		} else {
732
			brcmf_err("ignore IF event\n");
733 734
			return ERR_PTR(-EINVAL);
		}
735
	}
736

737
	/* Allocate netdev, including space for private structure */
738 739
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
740
		brcmf_err("OOM - alloc_netdev\n");
741
		return ERR_PTR(-ENOMEM);
742
	}
743

744 745
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
746
	ifp->drvr = drvr;
747 748
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
749
	ifp->bssidx = bssidx;
750 751


752 753
	init_waitqueue_head(&ifp->pend_8021x_wait);

754 755
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
756

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

760
	return ifp;
761 762
}

763
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
764 765 766
{
	struct brcmf_if *ifp;

767
	ifp = drvr->iflist[bssidx];
768
	if (!ifp) {
769
		brcmf_err("Null interface, idx=%d\n", bssidx);
770 771
		return;
	}
772
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
773
	if (ifp->ndev) {
774
		if (bssidx == 0) {
775 776 777 778 779 780 781 782 783
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

784 785 786 787
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
788

789
		unregister_netdev(ifp->ndev);
790 791
		drvr->iflist[bssidx] = NULL;
		if (bssidx == 0)
792
			brcmf_cfg80211_detach(drvr->config);
793
		free_netdev(ifp->ndev);
794 795 796
	}
}

797
int brcmf_attach(uint bus_hdrlen, struct device *dev)
798
{
799
	struct brcmf_pub *drvr = NULL;
800
	int ret = 0;
801 802 803 804

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
805 806
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
807
		return -ENOMEM;
808

809
	mutex_init(&drvr->proto_block);
810 811

	/* Link to bus module */
812 813
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
814
	drvr->bus_if->drvr = drvr;
815

816 817 818
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

819
	/* Attach and link in the protocol */
820 821
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
822
		brcmf_err("brcmf_prot_attach failed\n");
823 824 825
		goto fail;
	}

826 827 828
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

829 830
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

831
	return ret;
832 833

fail:
834
	brcmf_detach(dev);
835

836
	return ret;
837 838
}

839
int brcmf_bus_start(struct device *dev)
840 841
{
	int ret = -1;
842 843
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
844
	struct brcmf_if *ifp;
845
	struct brcmf_if *p2p_ifp;
846 847 848 849

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
850
	ret = brcmf_bus_init(bus_if);
851
	if (ret != 0) {
852
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
853 854 855
		return ret;
	}

856
	/* add primary networking interface */
857
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
858 859 860
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

861 862 863 864 865 866 867
	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;

868 869 870 871 872
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
873
	if (ret < 0)
874
		goto fail;
875

A
Arend van Spriel 已提交
876
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
877 878 879 880
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
881

882 883 884 885
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

886
	ret = brcmf_net_attach(ifp, false);
887
fail:
888
	if (ret < 0) {
889
		brcmf_err("failed: %d\n", ret);
890 891
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
892
		free_netdev(ifp->ndev);
893
		drvr->iflist[0] = NULL;
894 895 896 897
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
898
		return ret;
899
	}
900 901
	if ((brcmf_p2p_enable) && (p2p_ifp))
		brcmf_net_p2p_attach(p2p_ifp);
902

903 904 905 906 907 908 909 910
	return 0;
}

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

	if (drvr) {
911 912
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
913

914
		/* Stop the bus module */
A
Arend van Spriel 已提交
915
		brcmf_bus_stop(drvr->bus_if);
916 917 918
	}
}

919 920 921 922 923 924 925 926
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;

927 928
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
929 930
}

931
void brcmf_detach(struct device *dev)
932
{
933
	s32 i;
934 935
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
936 937 938

	brcmf_dbg(TRACE, "Enter\n");

939 940
	if (drvr == NULL)
		return;
941

942 943 944
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

945 946 947 948
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
		if (drvr->iflist[i])
			brcmf_del_if(drvr, i);
949

950
	brcmf_bus_detach(drvr);
951

952
	if (drvr->prot)
953
		brcmf_proto_detach(drvr);
954

955
	brcmf_debugfs_detach(drvr);
956 957
	bus_if->drvr = NULL;
	kfree(drvr);
958 959
}

960
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
961
{
962
	return atomic_read(&ifp->pend_8021x_cnt);
963 964 965 966
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
967
	struct brcmf_if *ifp = netdev_priv(ndev);
968 969
	int err;

970 971
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
972 973 974 975 976
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
977 978
}

979 980 981 982 983 984 985 986 987 988
/*
 * 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;
}

989
static void brcmf_driver_init(struct work_struct *work)
990
{
991 992
	brcmf_debugfs_init();

993
#ifdef CONFIG_BRCMFMAC_SDIO
994
	brcmf_sdio_init();
995
#endif
996
#ifdef CONFIG_BRCMFMAC_USB
997
	brcmf_usb_init();
998
#endif
999 1000 1001 1002 1003 1004 1005 1006
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

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

1007
	return 0;
1008 1009
}

1010
static void __exit brcmfmac_module_exit(void)
1011
{
1012 1013
	cancel_work_sync(&brcmf_driver_work);

1014 1015 1016
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1017 1018 1019
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1020
	brcmf_debugfs_exit();
1021 1022
}

1023 1024
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);