dhd_linux.c 23.0 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

	sprintf(info->driver, KBUILD_MODNAME);
417
	sprintf(info->version, "%lu", drvr->drv_version);
A
Arend van Spriel 已提交
418
	sprintf(info->bus_info, "%s", dev_name(drvr->bus_if->dev));
419 420
}

421 422
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
423 424
};

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

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

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

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

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

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

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

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

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

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

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

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

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
545 546
	struct brcmf_if *ifp = netdev_priv(ndev);

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

549
	brcmf_cfg80211_down(ndev);
550

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

	return 0;
}

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

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

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

573
	atomic_set(&ifp->pend_8021x_cnt, 0);
574

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

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

	return ret;
}

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

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

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

611
	/* set appropriate operations */
612
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
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 624 625
	INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);

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

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

	return 0;

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

640 641 642 643 644 645 646 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
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;
}

703 704
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
705 706
{
	struct brcmf_if *ifp;
707
	struct net_device *ndev;
708

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

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

730
	/* Allocate netdev, including space for private structure */
731 732
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
733
		brcmf_err("OOM - alloc_netdev\n");
734
		return ERR_PTR(-ENOMEM);
735
	}
736

737 738
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
739
	ifp->drvr = drvr;
740 741
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
742
	ifp->bssidx = bssidx;
743 744


745 746
	init_waitqueue_head(&ifp->pend_8021x_wait);

747 748
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
749

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

753
	return ifp;
754 755
}

756
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
757 758 759
{
	struct brcmf_if *ifp;

760
	ifp = drvr->iflist[bssidx];
761
	if (!ifp) {
762
		brcmf_err("Null interface, idx=%d\n", bssidx);
763 764
		return;
	}
765
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
766
	if (ifp->ndev) {
767
		if (bssidx == 0) {
768 769 770 771 772 773 774 775 776
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

777 778 779 780
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
781

782
		unregister_netdev(ifp->ndev);
783 784
		drvr->iflist[bssidx] = NULL;
		if (bssidx == 0)
785
			brcmf_cfg80211_detach(drvr->config);
786
		free_netdev(ifp->ndev);
787 788 789
	}
}

790
int brcmf_attach(uint bus_hdrlen, struct device *dev)
791
{
792
	struct brcmf_pub *drvr = NULL;
793
	int ret = 0;
794 795 796 797

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
798 799
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
800
		return -ENOMEM;
801

802
	mutex_init(&drvr->proto_block);
803 804

	/* Link to bus module */
805 806
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
807
	drvr->bus_if->drvr = drvr;
808

809 810 811
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

812
	/* Attach and link in the protocol */
813 814
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
815
		brcmf_err("brcmf_prot_attach failed\n");
816 817 818
		goto fail;
	}

819 820 821
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

822 823
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

824
	return ret;
825 826

fail:
827
	brcmf_detach(dev);
828

829
	return ret;
830 831
}

832
int brcmf_bus_start(struct device *dev)
833 834
{
	int ret = -1;
835 836
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
837
	struct brcmf_if *ifp;
838
	struct brcmf_if *p2p_ifp;
839 840 841 842

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
843
	ret = brcmf_bus_init(bus_if);
844
	if (ret != 0) {
845
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
846 847 848
		return ret;
	}

849
	/* add primary networking interface */
850
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
851 852 853
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

854 855 856 857 858 859 860
	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;

861 862 863 864 865
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
866
	if (ret < 0)
867
		goto fail;
868

A
Arend van Spriel 已提交
869
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
870 871 872 873
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
874

875 876 877 878
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

879
	ret = brcmf_net_attach(ifp);
880
fail:
881
	if (ret < 0) {
882
		brcmf_err("failed: %d\n", ret);
883 884
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
885
		free_netdev(ifp->ndev);
886
		drvr->iflist[0] = NULL;
887 888 889 890
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
891
		return ret;
892
	}
893 894
	if ((brcmf_p2p_enable) && (p2p_ifp))
		brcmf_net_p2p_attach(p2p_ifp);
895

896 897 898 899 900 901 902 903
	return 0;
}

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

	if (drvr) {
904 905
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
906

907
		/* Stop the bus module */
A
Arend van Spriel 已提交
908
		brcmf_bus_stop(drvr->bus_if);
909 910 911
	}
}

912 913 914 915 916 917 918 919
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;

920 921
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
922 923
}

924
void brcmf_detach(struct device *dev)
925
{
926
	s32 i;
927 928
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
929 930 931

	brcmf_dbg(TRACE, "Enter\n");

932 933
	if (drvr == NULL)
		return;
934

935 936 937
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

938 939 940 941
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
		if (drvr->iflist[i])
			brcmf_del_if(drvr, i);
942

943
	brcmf_bus_detach(drvr);
944

945
	if (drvr->prot)
946
		brcmf_proto_detach(drvr);
947

948
	brcmf_debugfs_detach(drvr);
949 950
	bus_if->drvr = NULL;
	kfree(drvr);
951 952
}

953
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
954
{
955
	return atomic_read(&ifp->pend_8021x_cnt);
956 957 958 959
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
960
	struct brcmf_if *ifp = netdev_priv(ndev);
961 962
	int err;

963 964
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
965 966 967 968 969
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
970 971
}

972 973 974 975 976 977 978 979 980 981
/*
 * 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;
}

982
static void brcmf_driver_init(struct work_struct *work)
983
{
984 985
	brcmf_debugfs_init();

986
#ifdef CONFIG_BRCMFMAC_SDIO
987
	brcmf_sdio_init();
988
#endif
989
#ifdef CONFIG_BRCMFMAC_USB
990
	brcmf_usb_init();
991
#endif
992 993 994 995 996 997 998 999
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

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

1000
	return 0;
1001 1002
}

1003
static void __exit brcmfmac_module_exit(void)
1004
{
1005 1006
	cancel_work_sync(&brcmf_driver_work);

1007 1008 1009
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1010 1011 1012
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1013
	brcmf_debugfs_exit();
1014 1015
}

1016 1017
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);