dhd_linux.c 23.5 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 227 228 229 230
	/* 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)
231
		atomic_inc(&ifp->pend_8021x_cnt);
232

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

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

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

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

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

	brcmf_dbg(TRACE, "Enter\n");

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

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

	brcmf_dbg(TRACE, "Enter\n");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

done:
	brcmu_pkt_buf_free_skb(txp);
384 385 386 387
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
388
	struct brcmf_if *ifp = netdev_priv(ndev);
389

390
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
391 392 393 394

	return &ifp->stats;
}

395 396 397 398 399
/*
 * 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)
400
{
401
	s32 err;
402

403 404
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
405
		brcmf_err("Setting toe_ol failed, %d\n", err);
406
		return err;
407 408
	}

409 410
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
411
		brcmf_err("Setting toe failed, %d\n", err);
412

413
	return err;
414 415 416 417 418 419

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
420
	struct brcmf_if *ifp = netdev_priv(ndev);
421
	struct brcmf_pub *drvr = ifp->drvr;
422

423 424 425 426 427
	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));
428 429
}

430 431
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
432 433
};

434
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
435
{
436
	struct brcmf_pub *drvr = ifp->drvr;
437 438 439 440 441 442 443
	struct ethtool_drvinfo info;
	char drvname[sizeof(info.driver)];
	u32 cmd;
	struct ethtool_value edata;
	u32 toe_cmpnt, csum_dir;
	int ret;

444
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

	/* 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);
		}
467
		/* report dongle driver type */
468
		else
469
			sprintf(info.driver, "wl");
470

471
		sprintf(info.version, "%lu", drvr->drv_version);
472 473
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
474
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
475 476 477 478 479 480
			  (int)sizeof(drvname), drvname, info.driver);
		break;

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

514
		ret = brcmf_toe_set(ifp, toe_cmpnt);
515 516 517 518 519 520
		if (ret < 0)
			return ret;

		/* If setting TX checksum mode, tell Linux the new mode */
		if (cmd == ETHTOOL_STXCSUM) {
			if (edata.data)
521
				ifp->ndev->features |= NETIF_F_IP_CSUM;
522
			else
523
				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
524 525 526 527 528 529 530 531 532 533 534 535 536 537
		}

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
538
	struct brcmf_if *ifp = netdev_priv(ndev);
539
	struct brcmf_pub *drvr = ifp->drvr;
540

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

543
	if (!drvr->iflist[ifp->bssidx])
544 545 546
		return -1;

	if (cmd == SIOCETHTOOL)
547
		return brcmf_ethtool(ifp, ifr->ifr_data);
548 549 550 551 552 553

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
554
	struct brcmf_if *ifp = netdev_priv(ndev);
555

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

558
	brcmf_cfg80211_down(ndev);
559

560 561 562 563 564 565 566 567
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
568
	struct brcmf_if *ifp = netdev_priv(ndev);
569
	struct brcmf_pub *drvr = ifp->drvr;
570
	struct brcmf_bus *bus_if = drvr->bus_if;
571 572 573
	u32 toe_ol;
	s32 ret = 0;

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

576 577
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
578
		brcmf_err("failed bus is not ready\n");
579 580
		return -EAGAIN;
	}
581

582
	atomic_set(&ifp->pend_8021x_cnt, 0);
583

584 585 586
	/* 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)
587
		ndev->features |= NETIF_F_IP_CSUM;
588
	else
589
		ndev->features &= ~NETIF_F_IP_CSUM;
590

591 592
	/* Allow transmit calls */
	netif_start_queue(ndev);
593
	if (brcmf_cfg80211_up(ndev)) {
594
		brcmf_err("failed to bring up cfg80211\n");
595 596 597 598 599 600
		return -1;
	}

	return ret;
}

601 602 603 604 605 606 607 608 609 610
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
};

611
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
612
{
613
	struct brcmf_pub *drvr = ifp->drvr;
614
	struct net_device *ndev;
615
	s32 err;
616

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

621
	/* set appropriate operations */
622
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
623 624 625 626 627 628 629

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

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

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

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

636 637 638 639 640
	if (rtnl_locked)
		err = register_netdevice(ndev);
	else
		err = register_netdev(ndev);
	if (err != 0) {
641
		brcmf_err("couldn't register the net device\n");
642 643 644 645 646 647 648 649 650 651 652 653
		goto fail;
	}

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

	return 0;

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

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 710 711 712 713 714 715 716
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;
}

717 718
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
719 720
{
	struct brcmf_if *ifp;
721
	struct net_device *ndev;
722

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

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

744
	/* Allocate netdev, including space for private structure */
745 746
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
747
		brcmf_err("OOM - alloc_netdev\n");
748
		return ERR_PTR(-ENOMEM);
749
	}
750

751 752
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
753
	ifp->drvr = drvr;
754 755
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
756
	ifp->bssidx = bssidx;
757 758


759 760
	init_waitqueue_head(&ifp->pend_8021x_wait);

761 762
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
763

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

767
	return ifp;
768 769
}

770
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
771 772 773
{
	struct brcmf_if *ifp;

774
	ifp = drvr->iflist[bssidx];
775
	if (!ifp) {
776
		brcmf_err("Null interface, idx=%d\n", bssidx);
777 778
		return;
	}
779
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
780
	if (ifp->ndev) {
781
		if (bssidx == 0) {
782 783 784 785 786 787 788 789 790
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

791 792 793 794
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
795

796
		unregister_netdev(ifp->ndev);
797 798
		drvr->iflist[bssidx] = NULL;
		if (bssidx == 0)
799
			brcmf_cfg80211_detach(drvr->config);
800
		free_netdev(ifp->ndev);
801 802 803
	}
}

804
int brcmf_attach(uint bus_hdrlen, struct device *dev)
805
{
806
	struct brcmf_pub *drvr = NULL;
807
	int ret = 0;
808 809 810 811

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
812 813
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
814
		return -ENOMEM;
815

816
	mutex_init(&drvr->proto_block);
817 818

	/* Link to bus module */
819 820
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
821
	drvr->bus_if->drvr = drvr;
822

823 824 825
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

826
	/* Attach and link in the protocol */
827 828
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
829
		brcmf_err("brcmf_prot_attach failed\n");
830 831 832
		goto fail;
	}

833 834 835
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

836 837
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

838
	return ret;
839 840

fail:
841
	brcmf_detach(dev);
842

843
	return ret;
844 845
}

846
int brcmf_bus_start(struct device *dev)
847 848
{
	int ret = -1;
849 850
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
851
	struct brcmf_if *ifp;
852
	struct brcmf_if *p2p_ifp;
853 854 855 856

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
857
	ret = brcmf_bus_init(bus_if);
858
	if (ret != 0) {
859
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
860 861 862
		return ret;
	}

863
	/* add primary networking interface */
864
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
865 866 867
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

868 869 870 871 872 873 874
	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;

875 876 877 878 879
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
880
	if (ret < 0)
881
		goto fail;
882

883 884 885
	drvr->fw_signals = true;
	(void)brcmf_fws_init(drvr);

A
Arend van Spriel 已提交
886
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
887 888 889 890
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
891

892 893 894 895
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

896
	ret = brcmf_net_attach(ifp, false);
897
fail:
898
	if (ret < 0) {
899
		brcmf_err("failed: %d\n", ret);
900 901
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
902 903
		if (drvr->fws)
			brcmf_fws_deinit(drvr);
904
		free_netdev(ifp->ndev);
905
		drvr->iflist[0] = NULL;
906 907 908 909
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
910
		return ret;
911
	}
912 913
	if ((brcmf_p2p_enable) && (p2p_ifp))
		brcmf_net_p2p_attach(p2p_ifp);
914

915 916 917 918 919 920 921 922
	return 0;
}

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

	if (drvr) {
923 924
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
925

926
		/* Stop the bus module */
A
Arend van Spriel 已提交
927
		brcmf_bus_stop(drvr->bus_if);
928 929 930
	}
}

931 932 933 934 935 936 937 938
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;

939 940
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
941 942
}

943
void brcmf_detach(struct device *dev)
944
{
945
	s32 i;
946 947
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
948 949 950

	brcmf_dbg(TRACE, "Enter\n");

951 952
	if (drvr == NULL)
		return;
953

954 955 956
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

957 958 959 960
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
		if (drvr->iflist[i])
			brcmf_del_if(drvr, i);
961

962
	brcmf_bus_detach(drvr);
963

964
	if (drvr->prot)
965
		brcmf_proto_detach(drvr);
966

967 968 969
	if (drvr->fws)
		brcmf_fws_deinit(drvr);

970
	brcmf_debugfs_detach(drvr);
971 972
	bus_if->drvr = NULL;
	kfree(drvr);
973 974
}

975
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
976
{
977
	return atomic_read(&ifp->pend_8021x_cnt);
978 979 980 981
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
982
	struct brcmf_if *ifp = netdev_priv(ndev);
983 984
	int err;

985 986
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
987 988 989 990 991
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
992 993
}

994 995 996 997 998 999 1000 1001 1002 1003
/*
 * 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;
}

1004
static void brcmf_driver_init(struct work_struct *work)
1005
{
1006 1007
	brcmf_debugfs_init();

1008
#ifdef CONFIG_BRCMFMAC_SDIO
1009
	brcmf_sdio_init();
1010
#endif
1011
#ifdef CONFIG_BRCMFMAC_USB
1012
	brcmf_usb_init();
1013
#endif
1014 1015 1016 1017 1018 1019 1020 1021
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

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

1022
	return 0;
1023 1024
}

1025
static void __exit brcmfmac_module_exit(void)
1026
{
1027 1028
	cancel_work_sync(&brcmf_driver_work);

1029 1030 1031
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1032 1033 1034
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1035
	brcmf_debugfs_exit();
1036 1037
}

1038 1039
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);