| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-01-15 00:38:44 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/netdevice.h>
 | 
					
						
							|  |  |  | #include <brcmu_wifi.h>
 | 
					
						
							|  |  |  | #include <brcmu_utils.h>
 | 
					
						
							|  |  |  | #include "dhd.h"
 | 
					
						
							|  |  |  | #include "dhd_bus.h"
 | 
					
						
							|  |  |  | #include "dhd_dbg.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | #include "fwil.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:19 +01:00
										 |  |  | #include "fwil_types.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-03 12:45:21 +01:00
										 |  |  | #include "tracepoint.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | #define PKTFILTER_BUF_SIZE		128
 | 
					
						
							|  |  |  | #define BRCMF_DEFAULT_BCN_TIMEOUT	3
 | 
					
						
							|  |  |  | #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
 | 
					
						
							|  |  |  | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
 | 
					
						
							|  |  |  | #define BRCMF_DEFAULT_PACKET_FILTER	"100 0 0 0 0x01 0x00"
 | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-12 10:47:26 +02:00
										 |  |  | /* boost value for RSSI_DELTA in preferred join selection */ | 
					
						
							|  |  |  | #define BRCMF_JOIN_PREF_RSSI_BOOST	8
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-12 20:51:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-16 18:36:59 -08:00
										 |  |  | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		      struct sk_buff *pkt, int prec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sk_buff *p; | 
					
						
							|  |  |  | 	int eprec = -1;		/* precedence to evict from */ | 
					
						
							|  |  |  | 	bool discard_oldest; | 
					
						
							| 
									
										
										
										
											2011-12-16 18:36:59 -08:00
										 |  |  | 	struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = bus_if->drvr; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Fast case, precedence queue is not full and we are also not
 | 
					
						
							|  |  |  | 	 * exceeding total queue length | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (!pktq_pfull(q, prec) && !pktq_full(q)) { | 
					
						
							|  |  |  | 		brcmu_pktq_penq(q, prec, pkt); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Determine precedence from which to evict packet, if any */ | 
					
						
							|  |  |  | 	if (pktq_pfull(q, prec)) | 
					
						
							|  |  |  | 		eprec = prec; | 
					
						
							|  |  |  | 	else if (pktq_full(q)) { | 
					
						
							|  |  |  | 		p = brcmu_pktq_peek_tail(q, &eprec); | 
					
						
							|  |  |  | 		if (eprec > prec) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Evict if needed */ | 
					
						
							|  |  |  | 	if (eprec >= 0) { | 
					
						
							|  |  |  | 		/* Detect queueing to unconfigured precedence */ | 
					
						
							|  |  |  | 		discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); | 
					
						
							|  |  |  | 		if (eprec == prec && !discard_oldest) | 
					
						
							|  |  |  | 			return false;	/* refuse newer (incoming) packet */ | 
					
						
							|  |  |  | 		/* Evict packet according to discard policy */ | 
					
						
							|  |  |  | 		p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : | 
					
						
							|  |  |  | 			brcmu_pktq_pdeq_tail(q, eprec); | 
					
						
							|  |  |  | 		if (p == NULL) | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 			brcmf_err("brcmu_pktq_penq() failed, oldest %d\n", | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 				  discard_oldest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		brcmu_pkt_buf_free_skb(p); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Enqueue */ | 
					
						
							|  |  |  | 	p = brcmu_pktq_penq(q, prec, pkt); | 
					
						
							|  |  |  | 	if (p == NULL) | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("brcmu_pktq_penq() failed\n"); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return p != NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Convert user's input in hex pattern to byte-size mask */ | 
					
						
							|  |  |  | static int brcmf_c_pattern_atoh(char *src, char *dst) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Mask invalid format. Needs to start with 0x\n"); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	src = src + 2;		/* Skip past 0x */ | 
					
						
							|  |  |  | 	if (strlen(src) % 2 != 0) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Mask invalid format. Length must be even.\n"); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (i = 0; *src != '\0'; i++) { | 
					
						
							|  |  |  | 		unsigned long res; | 
					
						
							|  |  |  | 		char num[3]; | 
					
						
							|  |  |  | 		strncpy(num, src, 2); | 
					
						
							|  |  |  | 		num[2] = '\0'; | 
					
						
							|  |  |  | 		if (kstrtoul(num, 16, &res)) | 
					
						
							|  |  |  | 			return -EINVAL; | 
					
						
							|  |  |  | 		dst[i] = (u8)res; | 
					
						
							|  |  |  | 		src += 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | static void | 
					
						
							|  |  |  | brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, | 
					
						
							|  |  |  | 				 int master_mode) | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned long res; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	char *argv; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	char *arg_save = NULL, *arg_org = NULL; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	s32 err; | 
					
						
							| 
									
										
										
										
											2011-10-12 20:51:16 +02:00
										 |  |  | 	struct brcmf_pkt_filter_enable_le enable_parm; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	arg_save = kstrdup(arg, GFP_ATOMIC); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	if (!arg_save) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arg_org = arg_save; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	argv = strsep(&arg_save, " "); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	if (argv == NULL) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("No args provided\n"); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		goto fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse packet filter id. */ | 
					
						
							|  |  |  | 	enable_parm.id = 0; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	if (!kstrtoul(argv, 0, &res)) | 
					
						
							| 
									
										
										
										
											2011-10-12 20:51:16 +02:00
										 |  |  | 		enable_parm.id = cpu_to_le32((u32)res); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	/* Enable/disable the specified filter. */ | 
					
						
							| 
									
										
										
										
											2011-10-12 20:51:16 +02:00
										 |  |  | 	enable_parm.enable = cpu_to_le32(enable); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, | 
					
						
							|  |  |  | 				       sizeof(enable_parm)); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Set pkt_filter_enable error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	/* Control the master mode */ | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Set pkt_filter_mode error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  | 	kfree(arg_org); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	struct brcmf_pkt_filter_le *pkt_filter; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	unsigned long res; | 
					
						
							|  |  |  | 	int buf_len; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	s32 err; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	u32 mask_size; | 
					
						
							|  |  |  | 	u32 pattern_size; | 
					
						
							|  |  |  | 	char *argv[8], *buf = NULL; | 
					
						
							|  |  |  | 	int i = 0; | 
					
						
							|  |  |  | 	char *arg_save = NULL, *arg_org = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arg_save = kstrdup(arg, GFP_ATOMIC); | 
					
						
							|  |  |  | 	if (!arg_save) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arg_org = arg_save; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); | 
					
						
							|  |  |  | 	if (!buf) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	argv[i] = strsep(&arg_save, " "); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	while (argv[i]) { | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 		if (i >= 8) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 			brcmf_err("Too many parameters\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 			goto fail; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		argv[i] = strsep(&arg_save, " "); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	if (i != 6) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Not enough args provided %d\n", i); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		goto fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter = (struct brcmf_pkt_filter_le *)buf; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse packet filter id. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter->id = 0; | 
					
						
							|  |  |  | 	if (!kstrtoul(argv[0], 0, &res)) | 
					
						
							|  |  |  | 		pkt_filter->id = cpu_to_le32((u32)res); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse filter polarity. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter->negate_match = 0; | 
					
						
							|  |  |  | 	if (!kstrtoul(argv[1], 0, &res)) | 
					
						
							|  |  |  | 		pkt_filter->negate_match = cpu_to_le32((u32)res); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse filter type. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter->type = 0; | 
					
						
							|  |  |  | 	if (!kstrtoul(argv[2], 0, &res)) | 
					
						
							|  |  |  | 		pkt_filter->type = cpu_to_le32((u32)res); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse pattern filter offset. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter->u.pattern.offset = 0; | 
					
						
							|  |  |  | 	if (!kstrtoul(argv[3], 0, &res)) | 
					
						
							|  |  |  | 		pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse pattern filter mask. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	mask_size = brcmf_c_pattern_atoh(argv[4], | 
					
						
							|  |  |  | 			(char *)pkt_filter->u.pattern.mask_and_pattern); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse pattern filter pattern. */ | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pattern_size = brcmf_c_pattern_atoh(argv[5], | 
					
						
							|  |  |  | 		(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (mask_size != pattern_size) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Mask and pattern not the same size\n"); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 		goto fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); | 
					
						
							| 
									
										
										
										
											2012-11-05 16:22:17 -08:00
										 |  |  | 	buf_len = offsetof(struct brcmf_pkt_filter_le, | 
					
						
							|  |  |  | 			   u.pattern.mask_and_pattern); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	buf_len += mask_size + pattern_size; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, | 
					
						
							|  |  |  | 				       buf_len); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Set pkt_filter_add error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  | 	kfree(arg_org); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	kfree(buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 
					
						
							|  |  |  | 	u8 buf[BRCMF_DCMD_SMLEN]; | 
					
						
							| 
									
										
										
										
											2014-05-12 10:47:26 +02:00
										 |  |  | 	struct brcmf_join_pref_params join_pref_params[2]; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	char *ptr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	/* retreive mac address */ | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | 
					
						
							|  |  |  | 				       sizeof(ifp->mac_addr)); | 
					
						
							|  |  |  | 	if (err < 0) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Retreiving cur_etheraddr failed, %d\n", | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 			  err); | 
					
						
							|  |  |  | 		goto done; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* query for 'ver' to get version info from firmware */ | 
					
						
							|  |  |  | 	memset(buf, 0, sizeof(buf)); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	strcpy(buf, "ver"); | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); | 
					
						
							|  |  |  | 	if (err < 0) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Retreiving version information failed, %d\n", | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 			  err); | 
					
						
							|  |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ptr = (char *)buf; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	strsep(&ptr, "\n"); | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 	/* Print fw version info */ | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 	brcmf_err("Firmware version = %s\n", buf); | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:17 +01:00
										 |  |  | 	/* locate firmware version number for ethtool */ | 
					
						
							|  |  |  | 	ptr = strrchr(buf, ' ') + 1; | 
					
						
							|  |  |  | 	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Setup timeout if Beacons are lost and roam is off to report | 
					
						
							|  |  |  | 	 * link down | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", | 
					
						
							|  |  |  | 				      BRCMF_DEFAULT_BCN_TIMEOUT); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("bcn_timeout error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Enable/Disable build-in roaming to allowed ext supplicant to take
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	 * of romaing | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("roam_off error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-12 10:47:26 +02:00
										 |  |  | 	/* Setup join_pref to select target by RSSI(with boost on 5GHz) */ | 
					
						
							|  |  |  | 	join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; | 
					
						
							|  |  |  | 	join_pref_params[0].len = 2; | 
					
						
							|  |  |  | 	join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; | 
					
						
							|  |  |  | 	join_pref_params[0].band = WLC_BAND_5G; | 
					
						
							|  |  |  | 	join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; | 
					
						
							|  |  |  | 	join_pref_params[1].len = 2; | 
					
						
							|  |  |  | 	join_pref_params[1].rssi_gain = 0; | 
					
						
							|  |  |  | 	join_pref_params[1].band = 0; | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, | 
					
						
							|  |  |  | 				       sizeof(join_pref_params)); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							|  |  |  | 		brcmf_err("Set join_pref error (%d)\n", err); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 	/* Setup event_msgs, enable E_IF */ | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, | 
					
						
							|  |  |  | 				       BRCMF_EVENTING_MASK_LEN); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Get event_msgs error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	setbit(eventmask, BRCMF_E_IF); | 
					
						
							|  |  |  | 	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, | 
					
						
							|  |  |  | 				       BRCMF_EVENTING_MASK_LEN); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Set event_msgs error (%d)\n", err); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Setup default scan channel time */ | 
					
						
							|  |  |  | 	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | 
					
						
							|  |  |  | 				    BRCMF_DEFAULT_SCAN_CHANNEL_TIME); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 			  err); | 
					
						
							|  |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Setup default scan unassoc time */ | 
					
						
							|  |  |  | 	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | 
					
						
							|  |  |  | 				    BRCMF_DEFAULT_SCAN_UNASSOC_TIME); | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | 			  err); | 
					
						
							|  |  |  | 		goto done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Setup packet filter */ | 
					
						
							|  |  |  | 	brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); | 
					
						
							|  |  |  | 	brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | 
					
						
							|  |  |  | 					 0, true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-29 11:48:15 +01:00
										 |  |  | 	/* do bus specific preinit here */ | 
					
						
							|  |  |  | 	err = brcmf_bus_preinit(ifp->drvr->bus_if); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:25 -07:00
										 |  |  | done: | 
					
						
							|  |  |  | 	return err; | 
					
						
							| 
									
										
										
										
											2011-10-05 13:19:03 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-03 12:45:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_BRCM_TRACING
 | 
					
						
							|  |  |  | void __brcmf_err(const char *func, const char *fmt, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct va_format vaf = { | 
					
						
							|  |  |  | 		.fmt = fmt, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	va_list args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_start(args, fmt); | 
					
						
							|  |  |  | 	vaf.va = &args; | 
					
						
							|  |  |  | 	pr_err("%s: %pV", func, &vaf); | 
					
						
							|  |  |  | 	trace_brcmf_err(func, &vaf); | 
					
						
							|  |  |  | 	va_end(args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
 | 
					
						
							|  |  |  | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct va_format vaf = { | 
					
						
							|  |  |  | 		.fmt = fmt, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	va_list args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_start(args, fmt); | 
					
						
							|  |  |  | 	vaf.va = &args; | 
					
						
							|  |  |  | 	if (brcmf_msg_level & level) | 
					
						
							|  |  |  | 		pr_debug("%s %pV", func, &vaf); | 
					
						
							|  |  |  | 	trace_brcmf_dbg(level, func, &vaf); | 
					
						
							|  |  |  | 	va_end(args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |