dhd_common.c 9.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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.
 */
16

17 18 19 20 21 22 23 24
#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"
25
#include "fwil.h"
26
#include "tracepoint.h"
27

28 29 30 31 32
#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"
33

J
Joe Perches 已提交
34
#ifdef DEBUG
35 36 37 38 39 40 41 42
static const char brcmf_version[] =
	"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on "
	__DATE__ " at " __TIME__;
#else
static const char brcmf_version[] =
	"Dongle Host Driver, version " BRCMF_VERSION_STR;
#endif

43

44
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
45 46 47 48 49
		      struct sk_buff *pkt, int prec)
{
	struct sk_buff *p;
	int eprec = -1;		/* precedence to evict from */
	bool discard_oldest;
50 51
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_pub *drvr = bus_if->drvr;
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

	/* 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)
80
			brcmf_err("brcmu_pktq_penq() failed, oldest %d\n",
81 82 83 84 85 86 87 88
				  discard_oldest);

		brcmu_pkt_buf_free_skb(p);
	}

	/* Enqueue */
	p = brcmu_pktq_penq(q, prec, pkt);
	if (p == NULL)
89
		brcmf_err("brcmu_pktq_penq() failed\n");
90 91 92 93 94 95 96 97 98

	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) {
99
		brcmf_err("Mask invalid format. Needs to start with 0x\n");
100 101 102 103
		return -EINVAL;
	}
	src = src + 2;		/* Skip past 0x */
	if (strlen(src) % 2 != 0) {
104
		brcmf_err("Mask invalid format. Length must be even.\n");
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
		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;
}

120 121 122
static void
brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
				 int master_mode)
123 124
{
	unsigned long res;
125
	char *argv;
126
	char *arg_save = NULL, *arg_org = NULL;
127
	s32 err;
128
	struct brcmf_pkt_filter_enable_le enable_parm;
129

130
	arg_save = kstrdup(arg, GFP_ATOMIC);
131 132 133 134 135
	if (!arg_save)
		goto fail;

	arg_org = arg_save;

136
	argv = strsep(&arg_save, " ");
137

138
	if (argv == NULL) {
139
		brcmf_err("No args provided\n");
140 141 142 143 144
		goto fail;
	}

	/* Parse packet filter id. */
	enable_parm.id = 0;
145
	if (!kstrtoul(argv, 0, &res))
146
		enable_parm.id = cpu_to_le32((u32)res);
147

148
	/* Enable/disable the specified filter. */
149
	enable_parm.enable = cpu_to_le32(enable);
150

151 152 153
	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
				       sizeof(enable_parm));
	if (err)
154
		brcmf_err("Set pkt_filter_enable error (%d)\n", err);
155

156 157 158
	/* Control the master mode */
	err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
	if (err)
159
		brcmf_err("Set pkt_filter_mode error (%d)\n", err);
160 161 162 163 164

fail:
	kfree(arg_org);
}

165
static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
166
{
167
	struct brcmf_pkt_filter_le *pkt_filter;
168 169
	unsigned long res;
	int buf_len;
170
	s32 err;
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
	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, " ");
188 189 190
	while (argv[i]) {
		i++;
		if (i >= 8) {
191
			brcmf_err("Too many parameters\n");
192 193
			goto fail;
		}
194
		argv[i] = strsep(&arg_save, " ");
195
	}
196

197
	if (i != 6) {
198
		brcmf_err("Not enough args provided %d\n", i);
199 200 201
		goto fail;
	}

202
	pkt_filter = (struct brcmf_pkt_filter_le *)buf;
203 204

	/* Parse packet filter id. */
205 206 207
	pkt_filter->id = 0;
	if (!kstrtoul(argv[0], 0, &res))
		pkt_filter->id = cpu_to_le32((u32)res);
208 209

	/* Parse filter polarity. */
210 211 212
	pkt_filter->negate_match = 0;
	if (!kstrtoul(argv[1], 0, &res))
		pkt_filter->negate_match = cpu_to_le32((u32)res);
213 214

	/* Parse filter type. */
215 216 217
	pkt_filter->type = 0;
	if (!kstrtoul(argv[2], 0, &res))
		pkt_filter->type = cpu_to_le32((u32)res);
218 219

	/* Parse pattern filter offset. */
220 221 222
	pkt_filter->u.pattern.offset = 0;
	if (!kstrtoul(argv[3], 0, &res))
		pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
223 224

	/* Parse pattern filter mask. */
225 226
	mask_size = brcmf_c_pattern_atoh(argv[4],
			(char *)pkt_filter->u.pattern.mask_and_pattern);
227 228

	/* Parse pattern filter pattern. */
229 230
	pattern_size = brcmf_c_pattern_atoh(argv[5],
		(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
231 232

	if (mask_size != pattern_size) {
233
		brcmf_err("Mask and pattern not the same size\n");
234 235 236
		goto fail;
	}

237
	pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
238 239
	buf_len = offsetof(struct brcmf_pkt_filter_le,
			   u.pattern.mask_and_pattern);
240
	buf_len += mask_size + pattern_size;
241

242 243 244
	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
				       buf_len);
	if (err)
245
		brcmf_err("Set pkt_filter_add error (%d)\n", err);
246 247 248 249 250 251 252

fail:
	kfree(arg_org);

	kfree(buf);
}

253
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
254
{
255 256 257 258
	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
	u8 buf[BRCMF_DCMD_SMLEN];
	char *ptr;
	s32 err;
259

260 261 262 263
	/* retreive mac address */
	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
				       sizeof(ifp->mac_addr));
	if (err < 0) {
264
		brcmf_err("Retreiving cur_etheraddr failed, %d\n",
265 266
			  err);
		goto done;
267
	}
268
	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
269 270 271

	/* query for 'ver' to get version info from firmware */
	memset(buf, 0, sizeof(buf));
272 273 274
	strcpy(buf, "ver");
	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
	if (err < 0) {
275
		brcmf_err("Retreiving version information failed, %d\n",
276 277 278 279
			  err);
		goto done;
	}
	ptr = (char *)buf;
280
	strsep(&ptr, "\n");
281

282
	/* Print fw version info */
283
	brcmf_err("Firmware version = %s\n", buf);
284

285 286 287 288
	/* locate firmware version number for ethtool */
	ptr = strrchr(buf, ' ') + 1;
	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));

289 290 291 292 293 294 295
	/*
	 * 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) {
296
		brcmf_err("bcn_timeout error (%d)\n", err);
297 298
		goto done;
	}
299 300

	/* Enable/Disable build-in roaming to allowed ext supplicant to take
301 302 303 304
	 * of romaing
	 */
	err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
	if (err) {
305
		brcmf_err("roam_off error (%d)\n", err);
306 307 308 309 310 311 312
		goto done;
	}

	/* Setup event_msgs, enable E_IF */
	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
				       BRCMF_EVENTING_MASK_LEN);
	if (err) {
313
		brcmf_err("Get event_msgs error (%d)\n", err);
314 315 316 317 318 319
		goto done;
	}
	setbit(eventmask, BRCMF_E_IF);
	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
				       BRCMF_EVENTING_MASK_LEN);
	if (err) {
320
		brcmf_err("Set event_msgs error (%d)\n", err);
321 322 323 324 325 326 327
		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) {
328
		brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
329 330 331 332 333 334 335 336
			  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) {
337
		brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
338 339 340 341 342 343 344 345 346
			  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);

347 348
	/* do bus specific preinit here */
	err = brcmf_bus_preinit(ifp->drvr->bus_if);
349 350
done:
	return err;
351
}
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383

#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