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, 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 367 368
	ifp = drvr->iflist[ifidx];
	if (!ifp)
		return;

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 384
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
385
	struct brcmf_if *ifp = netdev_priv(ndev);
386

387
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
388 389 390 391

	return &ifp->stats;
}

392 393 394 395 396
/*
 * 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)
397
{
398
	s32 err;
399

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

406 407
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
408
		brcmf_err("Setting toe failed, %d\n", err);
409

410
	return err;
411 412 413 414 415 416

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
417
	struct brcmf_if *ifp = netdev_priv(ndev);
418
	struct brcmf_pub *drvr = ifp->drvr;
419

420 421 422 423 424
	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));
425 426
}

427 428
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
429 430
};

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

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

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

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

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

511
		ret = brcmf_toe_set(ifp, toe_cmpnt);
512 513 514 515 516 517
		if (ret < 0)
			return ret;

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

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
535
	struct brcmf_if *ifp = netdev_priv(ndev);
536
	struct brcmf_pub *drvr = ifp->drvr;
537

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

540
	if (!drvr->iflist[ifp->bssidx])
541 542 543
		return -1;

	if (cmd == SIOCETHTOOL)
544
		return brcmf_ethtool(ifp, ifr->ifr_data);
545 546 547 548 549 550

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
551
	struct brcmf_if *ifp = netdev_priv(ndev);
552

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

555
	brcmf_cfg80211_down(ndev);
556

557 558 559 560 561 562 563 564
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

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

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

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

579
	atomic_set(&ifp->pend_8021x_cnt, 0);
580

581 582 583
	/* 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)
584
		ndev->features |= NETIF_F_IP_CSUM;
585
	else
586
		ndev->features &= ~NETIF_F_IP_CSUM;
587

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

	return ret;
}

598 599 600 601 602 603 604 605 606 607
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
};

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

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

618
	/* set appropriate operations */
619
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
620 621 622 623 624 625 626

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

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

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

630 631 632
	INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);

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

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

	return 0;

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

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

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

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

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

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

748 749
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
750
	ifp->drvr = drvr;
751 752
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
753
	ifp->bssidx = bssidx;
754 755


756 757
	init_waitqueue_head(&ifp->pend_8021x_wait);

758 759
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
760

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

764
	return ifp;
765 766
}

767
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
768 769 770
{
	struct brcmf_if *ifp;

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

788 789 790 791
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
792

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

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

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
809 810
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
811
		return -ENOMEM;
812

813
	mutex_init(&drvr->proto_block);
814 815

	/* Link to bus module */
816 817
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
818
	drvr->bus_if->drvr = drvr;
819

820 821 822
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

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

830 831 832
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

833 834
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

835
	return ret;
836 837

fail:
838
	brcmf_detach(dev);
839

840
	return ret;
841 842
}

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

	brcmf_dbg(TRACE, "\n");

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

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

865 866 867 868 869 870 871
	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;

872 873 874 875 876
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
877
	if (ret < 0)
878
		goto fail;
879

880 881 882
	drvr->fw_signals = true;
	(void)brcmf_fws_init(drvr);

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

889 890 891 892
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

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

912 913 914 915 916 917 918 919
	return 0;
}

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

	if (drvr) {
920 921
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
922

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

928 929 930 931 932 933 934 935
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;

936 937
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
938 939
}

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

	brcmf_dbg(TRACE, "Enter\n");

948 949
	if (drvr == NULL)
		return;
950

951 952 953
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

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

959
	brcmf_bus_detach(drvr);
960

961
	if (drvr->prot)
962
		brcmf_proto_detach(drvr);
963

964 965 966
	if (drvr->fws)
		brcmf_fws_deinit(drvr);

967
	brcmf_debugfs_detach(drvr);
968 969
	bus_if->drvr = NULL;
	kfree(drvr);
970 971
}

972
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
973
{
974
	return atomic_read(&ifp->pend_8021x_cnt);
975 976 977 978
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
979
	struct brcmf_if *ifp = netdev_priv(ndev);
980 981
	int err;

982 983
	err = wait_event_timeout(ifp->pend_8021x_wait,
				 !brcmf_get_pend_8021x_cnt(ifp),
984 985 986 987 988
				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));

	WARN_ON(!err);

	return !err;
989 990
}

991 992 993 994 995 996 997 998 999 1000
/*
 * 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;
}

1001
static void brcmf_driver_init(struct work_struct *work)
1002
{
1003 1004
	brcmf_debugfs_init();

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

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

1019
	return 0;
1020 1021
}

1022
static void __exit brcmfmac_module_exit(void)
1023
{
1024 1025
	cancel_work_sync(&brcmf_driver_work);

1026 1027 1028
#ifdef CONFIG_BRCMFMAC_SDIO
	brcmf_sdio_exit();
#endif
1029 1030 1031
#ifdef CONFIG_BRCMFMAC_USB
	brcmf_usb_exit();
#endif
1032
	brcmf_debugfs_exit();
1033 1034
}

1035 1036
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);