dhd_linux.c 24.6 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(DATA, "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
void brcmf_txflowblock_if(struct brcmf_if *ifp,
			  enum brcmf_netif_stop_reason reason, bool state)
{
243 244
	unsigned long flags;

245 246 247 248 249
	if (!ifp)
		return;

	brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
		  ifp->bssidx, ifp->netif_stop, reason, state);
250 251

	spin_lock_irqsave(&ifp->netif_stop_lock, flags);
252 253 254 255 256 257 258 259 260
	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);
	}
261
	spin_unlock_irqrestore(&ifp->netif_stop_lock, flags);
262 263
}

264
void brcmf_txflowblock(struct device *dev, bool state)
265
{
266 267
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
268
	int i;
269 270 271

	brcmf_dbg(TRACE, "Enter\n");

272 273 274 275 276 277 278 279
	if (brcmf_fws_fc_active(drvr->fws)) {
		brcmf_fws_bus_blocked(drvr, state);
	} else {
		for (i = 0; i < BRCMF_MAX_IFS; i++)
			brcmf_txflowblock_if(drvr->iflist[i],
					     BRCMF_NETIF_STOP_REASON_BLOCK_BUS,
					     state);
	}
280 281
}

282
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
283 284 285
{
	unsigned char *eth;
	uint len;
286
	struct sk_buff *skb, *pnext;
287
	struct brcmf_if *ifp;
288 289
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
290 291
	u8 ifidx;
	int ret;
292

293
	brcmf_dbg(DATA, "Enter\n");
294

295 296
	skb_queue_walk_safe(skb_list, skb, pnext) {
		skb_unlink(skb, skb_list);
297

298
		/* process and remove protocol-specific header */
299
		ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb);
300 301 302 303 304
		ifp = drvr->iflist[ifidx];

		if (ret || !ifp || !ifp->ndev) {
			if ((ret != -ENODATA) && ifp)
				ifp->stats.rx_errors++;
305 306 307 308
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
		/* 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)
328
			ifp->stats.multicast++;
329 330 331 332 333 334 335

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

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

336 337
		/* Process special event packets */
		brcmf_fweh_process_skb(drvr, skb);
338

339 340 341 342 343 344 345
		if (!(ifp->ndev->flags & IFF_UP)) {
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

		ifp->stats.rx_bytes += skb->len;
		ifp->stats.rx_packets++;
346 347 348 349 350 351 352 353 354 355 356 357 358 359

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

360 361
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
		      bool success)
362
{
363
	struct brcmf_if *ifp;
364
	struct ethhdr *eh;
365
	u8 ifidx;
366
	u16 type;
367
	int res;
368

369
	res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
370

371 372
	ifp = drvr->iflist[ifidx];
	if (!ifp)
373
		goto done;
374

375 376 377
	if (res == 0) {
		eh = (struct ethhdr *)(txp->data);
		type = ntohs(eh->h_proto);
378

379 380 381 382 383
		if (type == ETH_P_PAE) {
			atomic_dec(&ifp->pend_8021x_cnt);
			if (waitqueue_active(&ifp->pend_8021x_wait))
				wake_up(&ifp->pend_8021x_wait);
		}
384
	}
385 386
	if (!success)
		ifp->stats.tx_errors++;
387 388
done:
	brcmu_pkt_buf_free_skb(txp);
389
}
390

391 392 393 394 395
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;

396 397 398 399 400 401 402
	/* 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);
	}
403 404 405 406
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
407
	struct brcmf_if *ifp = netdev_priv(ndev);
408

409
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
410 411 412 413

	return &ifp->stats;
}

414 415 416 417 418
/*
 * 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)
419
{
420
	s32 err;
421

422 423
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
424
		brcmf_err("Setting toe_ol failed, %d\n", err);
425
		return err;
426 427
	}

428 429
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
430
		brcmf_err("Setting toe failed, %d\n", err);
431

432
	return err;
433 434 435 436 437 438

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
439
	struct brcmf_if *ifp = netdev_priv(ndev);
440
	struct brcmf_pub *drvr = ifp->drvr;
441

442 443 444 445 446
	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));
447 448
}

449 450
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
451 452
};

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

463
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485

	/* 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);
		}
486
		/* report dongle driver type */
487
		else
488
			sprintf(info.driver, "wl");
489

490
		sprintf(info.version, "%lu", drvr->drv_version);
491 492
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
493
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
494 495 496 497 498 499
			  (int)sizeof(drvname), drvname, info.driver);
		break;

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

533
		ret = brcmf_toe_set(ifp, toe_cmpnt);
534 535 536 537 538 539
		if (ret < 0)
			return ret;

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

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
557
	struct brcmf_if *ifp = netdev_priv(ndev);
558
	struct brcmf_pub *drvr = ifp->drvr;
559

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

562
	if (!drvr->iflist[ifp->bssidx])
563 564 565
		return -1;

	if (cmd == SIOCETHTOOL)
566
		return brcmf_ethtool(ifp, ifr->ifr_data);
567 568 569 570 571 572

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
573
	struct brcmf_if *ifp = netdev_priv(ndev);
574

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

577
	brcmf_cfg80211_down(ndev);
578

579 580 581 582 583 584 585 586
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
587
	struct brcmf_if *ifp = netdev_priv(ndev);
588
	struct brcmf_pub *drvr = ifp->drvr;
589
	struct brcmf_bus *bus_if = drvr->bus_if;
590 591 592
	u32 toe_ol;
	s32 ret = 0;

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

595 596
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
597
		brcmf_err("failed bus is not ready\n");
598 599
		return -EAGAIN;
	}
600

601
	atomic_set(&ifp->pend_8021x_cnt, 0);
602

603 604 605
	/* 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)
606
		ndev->features |= NETIF_F_IP_CSUM;
607
	else
608
		ndev->features &= ~NETIF_F_IP_CSUM;
609

610 611
	/* Allow transmit calls */
	netif_start_queue(ndev);
612
	if (brcmf_cfg80211_up(ndev)) {
613
		brcmf_err("failed to bring up cfg80211\n");
614 615 616 617 618 619
		return -1;
	}

	return ret;
}

620 621 622 623 624 625 626 627 628 629
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
};

630
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
631
{
632
	struct brcmf_pub *drvr = ifp->drvr;
633
	struct net_device *ndev;
634
	s32 err;
635

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

640
	/* set appropriate operations */
641
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
642

643
	ndev->hard_header_len += drvr->hdrlen;
644 645 646 647 648
	ndev->ethtool_ops = &brcmf_ethtool_ops;

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

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

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

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

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

666
	ndev->destructor = free_netdev;
667 668 669
	return 0;

fail:
670
	drvr->iflist[ifp->bssidx] = NULL;
671
	ndev->netdev_ops = NULL;
672
	free_netdev(ndev);
673 674 675
	return -EBADE;
}

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 731 732 733 734 735
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:
736 737 738
	ifp->drvr->iflist[ifp->bssidx] = NULL;
	ndev->netdev_ops = NULL;
	free_netdev(ndev);
739 740 741
	return -EBADE;
}

742 743
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
744 745
{
	struct brcmf_if *ifp;
746
	struct net_device *ndev;
747

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

750
	ifp = drvr->iflist[bssidx];
751 752 753 754 755
	/*
	 * Delete the existing interface before overwriting it
	 * in case we missed the BRCMF_E_IF_DEL event.
	 */
	if (ifp) {
756
		brcmf_err("ERROR: netdev:%s already exists\n",
757
			  ifp->ndev->name);
758 759 760 761
		if (ifidx) {
			netif_stop_queue(ifp->ndev);
			unregister_netdev(ifp->ndev);
			free_netdev(ifp->ndev);
762
			drvr->iflist[bssidx] = NULL;
763
		} else {
764
			brcmf_err("ignore IF event\n");
765 766
			return ERR_PTR(-EINVAL);
		}
767
	}
768

769 770 771 772
	if (!brcmf_p2p_enable && bssidx == 1) {
		/* this is P2P_DEVICE interface */
		brcmf_dbg(INFO, "allocate non-netdev interface\n");
		ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
773 774
		if (!ifp)
			return ERR_PTR(-ENOMEM);
775 776 777 778
	} else {
		brcmf_dbg(INFO, "allocate netdev interface\n");
		/* Allocate netdev, including space for private structure */
		ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
779
		if (!ndev)
780 781 782 783
			return ERR_PTR(-ENOMEM);

		ifp = netdev_priv(ndev);
		ifp->ndev = ndev;
784
	}
785

786
	ifp->drvr = drvr;
787 788
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
789
	ifp->bssidx = bssidx;
790

791
	init_waitqueue_head(&ifp->pend_8021x_wait);
792
	spin_lock_init(&ifp->netif_stop_lock);
793

794 795
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
796

797
	brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
798
		  current->pid, name, ifp->mac_addr);
799

800
	return ifp;
801 802
}

803
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
804 805 806
{
	struct brcmf_if *ifp;

807
	ifp = drvr->iflist[bssidx];
808
	drvr->iflist[bssidx] = NULL;
809
	if (!ifp) {
810
		brcmf_err("Null interface, idx=%d\n", bssidx);
811 812
		return;
	}
813
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
814
	if (ifp->ndev) {
815
		if (bssidx == 0) {
816 817 818 819 820 821 822 823 824
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

825 826 827 828
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
829
		/* unregister will take care of freeing it */
830
		unregister_netdev(ifp->ndev);
831
		if (bssidx == 0)
832
			brcmf_cfg80211_detach(drvr->config);
833 834
	} else {
		kfree(ifp);
835 836 837
	}
}

838
int brcmf_attach(uint bus_hdrlen, struct device *dev)
839
{
840
	struct brcmf_pub *drvr = NULL;
841
	int ret = 0;
842 843 844 845

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
846 847
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
848
		return -ENOMEM;
849

850
	mutex_init(&drvr->proto_block);
851 852

	/* Link to bus module */
853 854
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
855
	drvr->bus_if->drvr = drvr;
856

857 858 859
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

860
	/* Attach and link in the protocol */
861 862
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
863
		brcmf_err("brcmf_prot_attach failed\n");
864 865 866
		goto fail;
	}

867 868 869
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

870 871
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

872
	return ret;
873 874

fail:
875
	brcmf_detach(dev);
876

877
	return ret;
878 879
}

880
int brcmf_bus_start(struct device *dev)
881 882
{
	int ret = -1;
883 884
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
885
	struct brcmf_if *ifp;
886
	struct brcmf_if *p2p_ifp;
887 888 889 890

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
A
Arend van Spriel 已提交
891
	ret = brcmf_bus_init(bus_if);
892
	if (ret != 0) {
893
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
894 895 896
		return ret;
	}

897
	/* add primary networking interface */
898
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
899 900 901
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

902 903 904 905 906 907 908
	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;

909 910 911 912 913
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
914
	if (ret < 0)
915
		goto fail;
916

917
	drvr->fw_signals = true;
918 919 920 921
	ret = brcmf_fws_init(drvr);
	if (ret < 0)
		goto fail;

922
	brcmf_fws_add_interface(ifp);
923

A
Arend van Spriel 已提交
924
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
925 926 927 928
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
929

930 931 932 933
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

934
	ret = brcmf_net_attach(ifp, false);
935
fail:
936
	if (ret < 0) {
937
		brcmf_err("failed: %d\n", ret);
938 939
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
940 941
		if (drvr->fws) {
			brcmf_fws_del_interface(ifp);
942
			brcmf_fws_deinit(drvr);
943
		}
944 945 946 947
		if (drvr->iflist[0]) {
			free_netdev(ifp->ndev);
			drvr->iflist[0] = NULL;
		}
948 949 950 951
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
952
		return ret;
953
	}
954
	if ((brcmf_p2p_enable) && (p2p_ifp))
955 956
		if (brcmf_net_p2p_attach(p2p_ifp) < 0)
			brcmf_p2p_enable = 0;
957

958 959 960 961 962 963 964 965
	return 0;
}

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

	if (drvr) {
966 967
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
968

969
		/* Stop the bus module */
A
Arend van Spriel 已提交
970
		brcmf_bus_stop(drvr->bus_if);
971 972 973
	}
}

974 975 976 977 978 979 980 981
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;

982 983
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
984 985
}

986
void brcmf_detach(struct device *dev)
987
{
988
	s32 i;
989 990
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
991 992 993

	brcmf_dbg(TRACE, "Enter\n");

994 995
	if (drvr == NULL)
		return;
996

997 998 999
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

1000 1001
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
1002 1003
		if (drvr->iflist[i]) {
			brcmf_fws_del_interface(drvr->iflist[i]);
1004
			brcmf_del_if(drvr, i);
1005
		}
1006

1007
	brcmf_bus_detach(drvr);
1008

1009
	if (drvr->prot)
1010
		brcmf_proto_detach(drvr);
1011

1012
	brcmf_fws_deinit(drvr);
1013

1014
	brcmf_debugfs_detach(drvr);
1015 1016
	bus_if->drvr = NULL;
	kfree(drvr);
1017 1018
}

1019
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
1020
{
1021
	return atomic_read(&ifp->pend_8021x_cnt);
1022 1023 1024 1025
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
1026
	struct brcmf_if *ifp = netdev_priv(ndev);
1027 1028
	int err;

1029 1030
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
1031 1032 1033 1034 1035
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
1036 1037
}

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
/*
 * 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;
}

1048
static void brcmf_driver_init(struct work_struct *work)
1049
{
1050 1051
	brcmf_debugfs_init();

1052
#ifdef CONFIG_BRCMFMAC_SDIO
1053
	brcmf_sdio_init();
1054
#endif
1055
#ifdef CONFIG_BRCMFMAC_USB
1056
	brcmf_usb_init();
1057
#endif
1058 1059 1060 1061 1062 1063 1064 1065
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);

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

1066
	return 0;
1067 1068
}

1069
static void __exit brcmfmac_module_exit(void)
1070
{
1071 1072
	cancel_work_sync(&brcmf_driver_work);

1073 1074 1075
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1076 1077 1078
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1079
	brcmf_debugfs_exit();
1080 1081
}

1082 1083
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);