dhd_linux.c 24 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");
Hante Meuleman's avatar
Hante Meuleman committed
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 */
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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
void brcmf_txflowblock_if(struct brcmf_if *ifp,
			  enum brcmf_netif_stop_reason reason, bool state)
{
	if (!ifp)
		return;

	brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
		  ifp->bssidx, ifp->netif_stop, reason, state);
	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);
	}
}

270
void brcmf_txflowblock(struct device *dev, bool state)
271
{
272
273
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
274
	int i;
275
276
277

	brcmf_dbg(TRACE, "Enter\n");

278
	for (i = 0; i < BRCMF_MAX_IFS; i++)
279
280
		brcmf_txflowblock_if(drvr->iflist[i],
				     BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
281
282
}

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

	brcmf_dbg(TRACE, "Enter\n");

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

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

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

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

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

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

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

340
341
		if (drvr->iflist[ifidx]) {
			ifp = drvr->iflist[ifidx];
342
			ifp->ndev->last_rx = jiffies;
343
		}
344

345
346
347
348
349
350
351
		if (!(ifp->ndev->flags & IFF_UP)) {
			brcmu_pkt_buf_free_skb(skb);
			continue;
		}

		ifp->stats.rx_bytes += skb->len;
		ifp->stats.rx_packets++;
352
353
354
355
356
357
358
359
360
361
362
363
364
365

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

366
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
367
{
368
	u8 ifidx;
369
370
	struct ethhdr *eh;
	u16 type;
371
372
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
373
	struct brcmf_if *ifp;
374
	int res;
375

376
	res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
377

378
379
	ifp = drvr->iflist[ifidx];
	if (!ifp)
380
		goto done;
381

382
383
384
	if (res == 0) {
		eh = (struct ethhdr *)(txp->data);
		type = ntohs(eh->h_proto);
385

386
387
388
389
390
		if (type == ETH_P_PAE) {
			atomic_dec(&ifp->pend_8021x_cnt);
			if (waitqueue_active(&ifp->pend_8021x_wait))
				wake_up(&ifp->pend_8021x_wait);
		}
391
	}
392
393
	if (!success)
		ifp->stats.tx_errors++;
394
395
396

done:
	brcmu_pkt_buf_free_skb(txp);
397
398
399
400
}

static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{
401
	struct brcmf_if *ifp = netdev_priv(ndev);
402

403
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
404
405
406
407

	return &ifp->stats;
}

408
409
410
411
412
/*
 * 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)
413
{
414
	s32 err;
415

416
417
	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
	if (err < 0) {
418
		brcmf_err("Setting toe_ol failed, %d\n", err);
419
		return err;
420
421
	}

422
423
	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
	if (err < 0)
424
		brcmf_err("Setting toe failed, %d\n", err);
425

426
	return err;
427
428
429
430
431
432

}

static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
				    struct ethtool_drvinfo *info)
{
433
	struct brcmf_if *ifp = netdev_priv(ndev);
434
	struct brcmf_pub *drvr = ifp->drvr;
435

436
437
438
439
440
	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));
441
442
}

443
444
static const struct ethtool_ops brcmf_ethtool_ops = {
	.get_drvinfo = brcmf_ethtool_get_drvinfo,
445
446
};

447
static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
448
{
449
	struct brcmf_pub *drvr = ifp->drvr;
450
451
452
453
454
455
456
	struct ethtool_drvinfo info;
	char drvname[sizeof(info.driver)];
	u32 cmd;
	struct ethtool_value edata;
	u32 toe_cmpnt, csum_dir;
	int ret;

457
	brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

	/* 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);
		}
480
		/* report dongle driver type */
481
		else
482
			sprintf(info.driver, "wl");
483

484
		sprintf(info.version, "%lu", drvr->drv_version);
485
486
		if (copy_to_user(uaddr, &info, sizeof(info)))
			return -EFAULT;
487
		brcmf_dbg(TRACE, "given %*s, returning %s\n",
488
489
490
491
492
493
			  (int)sizeof(drvname), drvname, info.driver);
		break;

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

527
		ret = brcmf_toe_set(ifp, toe_cmpnt);
528
529
530
531
532
533
		if (ret < 0)
			return ret;

		/* If setting TX checksum mode, tell Linux the new mode */
		if (cmd == ETHTOOL_STXCSUM) {
			if (edata.data)
534
				ifp->ndev->features |= NETIF_F_IP_CSUM;
535
			else
536
				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
537
538
539
540
541
542
543
544
545
546
547
548
549
550
		}

		break;

	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
				    int cmd)
{
551
	struct brcmf_if *ifp = netdev_priv(ndev);
552
	struct brcmf_pub *drvr = ifp->drvr;
553

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

556
	if (!drvr->iflist[ifp->bssidx])
557
558
559
		return -1;

	if (cmd == SIOCETHTOOL)
560
		return brcmf_ethtool(ifp, ifr->ifr_data);
561
562
563
564
565
566

	return -EOPNOTSUPP;
}

static int brcmf_netdev_stop(struct net_device *ndev)
{
567
	struct brcmf_if *ifp = netdev_priv(ndev);
568

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

571
	brcmf_cfg80211_down(ndev);
572

573
574
575
576
577
578
579
580
	/* Set state and stop OS transmissions */
	netif_stop_queue(ndev);

	return 0;
}

static int brcmf_netdev_open(struct net_device *ndev)
{
581
	struct brcmf_if *ifp = netdev_priv(ndev);
582
	struct brcmf_pub *drvr = ifp->drvr;
583
	struct brcmf_bus *bus_if = drvr->bus_if;
584
585
586
	u32 toe_ol;
	s32 ret = 0;

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

589
590
	/* If bus is not ready, can't continue */
	if (bus_if->state != BRCMF_BUS_DATA) {
591
		brcmf_err("failed bus is not ready\n");
592
593
		return -EAGAIN;
	}
594

595
	atomic_set(&ifp->pend_8021x_cnt, 0);
596

597
598
599
	/* 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)
600
		ndev->features |= NETIF_F_IP_CSUM;
601
	else
602
		ndev->features &= ~NETIF_F_IP_CSUM;
603

604
605
	/* Allow transmit calls */
	netif_start_queue(ndev);
606
	if (brcmf_cfg80211_up(ndev)) {
607
		brcmf_err("failed to bring up cfg80211\n");
608
609
610
611
612
613
		return -1;
	}

	return ret;
}

614
615
616
617
618
619
620
621
622
623
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
};

624
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
625
{
626
	struct brcmf_pub *drvr = ifp->drvr;
627
	struct net_device *ndev;
628
	s32 err;
629

630
	brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
631
		  ifp->mac_addr);
632
	ndev = ifp->ndev;
633

634
	/* set appropriate operations */
635
	ndev->netdev_ops = &brcmf_netdev_ops_pri;
636
637
638
639
640
641
642

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

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

643
644
	/* set the mac address */
	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
645

646
647
648
	INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);

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

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

	return 0;

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

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
717
718
719
720
721
722
723
724
725
726
727
728
729
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;
}

730
731
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
			      char *name, u8 *mac_addr)
732
733
{
	struct brcmf_if *ifp;
734
	struct net_device *ndev;
735

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

738
	ifp = drvr->iflist[bssidx];
739
740
741
742
743
	/*
	 * Delete the existing interface before overwriting it
	 * in case we missed the BRCMF_E_IF_DEL event.
	 */
	if (ifp) {
744
		brcmf_err("ERROR: netdev:%s already exists\n",
745
			  ifp->ndev->name);
746
747
748
749
		if (ifidx) {
			netif_stop_queue(ifp->ndev);
			unregister_netdev(ifp->ndev);
			free_netdev(ifp->ndev);
750
			drvr->iflist[bssidx] = NULL;
751
		} else {
752
			brcmf_err("ignore IF event\n");
753
754
			return ERR_PTR(-EINVAL);
		}
755
	}
756

757
	/* Allocate netdev, including space for private structure */
758
759
	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
	if (!ndev) {
760
		brcmf_err("OOM - alloc_netdev\n");
761
		return ERR_PTR(-ENOMEM);
762
	}
763

764
765
	ifp = netdev_priv(ndev);
	ifp->ndev = ndev;
766
	ifp->drvr = drvr;
767
768
	drvr->iflist[bssidx] = ifp;
	ifp->ifidx = ifidx;
769
	ifp->bssidx = bssidx;
770

771
772
	init_waitqueue_head(&ifp->pend_8021x_wait);

773
774
	if (mac_addr != NULL)
		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
775

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

779
	return ifp;
780
781
}

782
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
783
784
785
{
	struct brcmf_if *ifp;

786
	ifp = drvr->iflist[bssidx];
787
	if (!ifp) {
788
		brcmf_err("Null interface, idx=%d\n", bssidx);
789
790
		return;
	}
791
	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
792
	if (ifp->ndev) {
793
		if (bssidx == 0) {
794
795
796
797
798
799
800
801
802
			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
				rtnl_lock();
				brcmf_netdev_stop(ifp->ndev);
				rtnl_unlock();
			}
		} else {
			netif_stop_queue(ifp->ndev);
		}

803
804
805
806
		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
			cancel_work_sync(&ifp->setmacaddr_work);
			cancel_work_sync(&ifp->multicast_work);
		}
807

808
		unregister_netdev(ifp->ndev);
809
810
		drvr->iflist[bssidx] = NULL;
		if (bssidx == 0)
811
			brcmf_cfg80211_detach(drvr->config);
812
		free_netdev(ifp->ndev);
813
814
815
	}
}

816
int brcmf_attach(uint bus_hdrlen, struct device *dev)
817
{
818
	struct brcmf_pub *drvr = NULL;
819
	int ret = 0;
820
821
822
823

	brcmf_dbg(TRACE, "Enter\n");

	/* Allocate primary brcmf_info */
824
825
	drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
	if (!drvr)
826
		return -ENOMEM;
827

828
	mutex_init(&drvr->proto_block);
829
830

	/* Link to bus module */
831
832
	drvr->hdrlen = bus_hdrlen;
	drvr->bus_if = dev_get_drvdata(dev);
833
	drvr->bus_if->drvr = drvr;
834

835
836
837
	/* create device debugfs folder */
	brcmf_debugfs_attach(drvr);

838
	/* Attach and link in the protocol */
839
840
	ret = brcmf_proto_attach(drvr);
	if (ret != 0) {
841
		brcmf_err("brcmf_prot_attach failed\n");
842
843
844
		goto fail;
	}

845
846
847
	/* attach firmware event handler */
	brcmf_fweh_attach(drvr);

848
849
	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);

850
	return ret;
851
852

fail:
853
	brcmf_detach(dev);
854

855
	return ret;
856
857
}

858
int brcmf_bus_start(struct device *dev)
859
860
{
	int ret = -1;
861
862
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
863
	struct brcmf_if *ifp;
864
	struct brcmf_if *p2p_ifp;
865
866
867
868

	brcmf_dbg(TRACE, "\n");

	/* Bring up the bus */
869
	ret = brcmf_bus_init(bus_if);
870
	if (ret != 0) {
871
		brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
872
873
874
		return ret;
	}

875
	/* add primary networking interface */
876
	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
877
878
879
	if (IS_ERR(ifp))
		return PTR_ERR(ifp);

880
881
882
883
884
885
886
	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;

887
888
889
890
891
	/* signal bus ready */
	bus_if->state = BRCMF_BUS_DATA;

	/* Bus is ready, do any initialization */
	ret = brcmf_c_preinit_dcmds(ifp);
892
	if (ret < 0)
893
		goto fail;
894

895
896
	drvr->fw_signals = true;
	(void)brcmf_fws_init(drvr);
897
	brcmf_fws_add_interface(ifp);
898

899
	drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
900
901
902
903
	if (drvr->config == NULL) {
		ret = -ENOMEM;
		goto fail;
	}
904

905
906
907
908
	ret = brcmf_fweh_activate_events(ifp);
	if (ret < 0)
		goto fail;

909
	ret = brcmf_net_attach(ifp, false);
910
fail:
911
	if (ret < 0) {
912
		brcmf_err("failed: %d\n", ret);
913
914
		if (drvr->config)
			brcmf_cfg80211_detach(drvr->config);
915
916
		if (drvr->fws) {
			brcmf_fws_del_interface(ifp);
917
			brcmf_fws_deinit(drvr);
918
		}
919
		free_netdev(ifp->ndev);
920
		drvr->iflist[0] = NULL;
921
922
923
924
		if (p2p_ifp) {
			free_netdev(p2p_ifp->ndev);
			drvr->iflist[1] = NULL;
		}
925
		return ret;
926
	}
927
928
	if ((brcmf_p2p_enable) && (p2p_ifp))
		brcmf_net_p2p_attach(p2p_ifp);
929

930
931
932
933
934
935
936
937
	return 0;
}

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

	if (drvr) {
938
939
		/* Stop the protocol module */
		brcmf_proto_stop(drvr);
940

941
		/* Stop the bus module */
942
		brcmf_bus_stop(drvr->bus_if);
943
944
945
	}
}

946
947
948
949
950
951
952
953
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;

954
955
	if (drvr->iflist[0])
		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
956
957
}

958
void brcmf_detach(struct device *dev)
959
{
960
	s32 i;
961
962
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
963
964
965

	brcmf_dbg(TRACE, "Enter\n");

966
967
	if (drvr == NULL)
		return;
968

969
970
971
	/* stop firmware event handling */
	brcmf_fweh_detach(drvr);

972
973
	/* make sure primary interface removed last */
	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
974
975
		if (drvr->iflist[i]) {
			brcmf_fws_del_interface(drvr->iflist[i]);
976
			brcmf_del_if(drvr, i);
977
		}
978

979
	brcmf_bus_detach(drvr);
980

981
	if (drvr->prot)
982
		brcmf_proto_detach(drvr);
983

984
985
986
	if (drvr->fws)
		brcmf_fws_deinit(drvr);

987
	brcmf_debugfs_detach(drvr);
988
989
	bus_if->drvr = NULL;
	kfree(drvr);
990
991
}

992
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
993
{
994
	return atomic_read(&ifp->pend_8021x_cnt);
995
996
997
998
}

int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{
999
	struct brcmf_if *ifp = netdev_priv(ndev);
1000
	int err;
For faster browsing, not all history is shown. View entire blame