| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2012 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* FWIL is the Firmware Interface Layer. In this module the support functions
 | 
					
						
							|  |  |  |  * are located to set and get variables to and from the firmware. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/netdevice.h>
 | 
					
						
							|  |  |  | #include <brcmu_utils.h>
 | 
					
						
							|  |  |  | #include <brcmu_wifi.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:18 +01:00
										 |  |  | #include "core.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:14 +01:00
										 |  |  | #include "bus.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:13 +01:00
										 |  |  | #include "debug.h"
 | 
					
						
							| 
									
										
										
										
											2013-04-05 10:57:44 +02:00
										 |  |  | #include "tracepoint.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:21 -07:00
										 |  |  | #include "fwil.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:16 +01:00
										 |  |  | #include "proto.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | #define MAX_HEX_DUMP_LEN	64
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:07 +01:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | static const char * const brcmf_fil_errstr[] = { | 
					
						
							|  |  |  | 	"BCME_OK", | 
					
						
							|  |  |  | 	"BCME_ERROR", | 
					
						
							|  |  |  | 	"BCME_BADARG", | 
					
						
							|  |  |  | 	"BCME_BADOPTION", | 
					
						
							|  |  |  | 	"BCME_NOTUP", | 
					
						
							|  |  |  | 	"BCME_NOTDOWN", | 
					
						
							|  |  |  | 	"BCME_NOTAP", | 
					
						
							|  |  |  | 	"BCME_NOTSTA", | 
					
						
							|  |  |  | 	"BCME_BADKEYIDX", | 
					
						
							|  |  |  | 	"BCME_RADIOOFF", | 
					
						
							|  |  |  | 	"BCME_NOTBANDLOCKED", | 
					
						
							|  |  |  | 	"BCME_NOCLK", | 
					
						
							|  |  |  | 	"BCME_BADRATESET", | 
					
						
							|  |  |  | 	"BCME_BADBAND", | 
					
						
							|  |  |  | 	"BCME_BUFTOOSHORT", | 
					
						
							|  |  |  | 	"BCME_BUFTOOLONG", | 
					
						
							|  |  |  | 	"BCME_BUSY", | 
					
						
							|  |  |  | 	"BCME_NOTASSOCIATED", | 
					
						
							|  |  |  | 	"BCME_BADSSIDLEN", | 
					
						
							|  |  |  | 	"BCME_OUTOFRANGECHAN", | 
					
						
							|  |  |  | 	"BCME_BADCHAN", | 
					
						
							|  |  |  | 	"BCME_BADADDR", | 
					
						
							|  |  |  | 	"BCME_NORESOURCE", | 
					
						
							|  |  |  | 	"BCME_UNSUPPORTED", | 
					
						
							|  |  |  | 	"BCME_BADLEN", | 
					
						
							|  |  |  | 	"BCME_NOTREADY", | 
					
						
							|  |  |  | 	"BCME_EPERM", | 
					
						
							|  |  |  | 	"BCME_NOMEM", | 
					
						
							|  |  |  | 	"BCME_ASSOCIATED", | 
					
						
							|  |  |  | 	"BCME_RANGE", | 
					
						
							|  |  |  | 	"BCME_NOTFOUND", | 
					
						
							|  |  |  | 	"BCME_WME_NOT_ENABLED", | 
					
						
							|  |  |  | 	"BCME_TSPEC_NOTFOUND", | 
					
						
							|  |  |  | 	"BCME_ACM_NOTSUPPORTED", | 
					
						
							|  |  |  | 	"BCME_NOT_WME_ASSOCIATION", | 
					
						
							|  |  |  | 	"BCME_SDIO_ERROR", | 
					
						
							|  |  |  | 	"BCME_DONGLE_DOWN", | 
					
						
							|  |  |  | 	"BCME_VERSION", | 
					
						
							|  |  |  | 	"BCME_TXFAIL", | 
					
						
							|  |  |  | 	"BCME_RXFAIL", | 
					
						
							|  |  |  | 	"BCME_NODEVICE", | 
					
						
							|  |  |  | 	"BCME_NMODE_DISABLED", | 
					
						
							|  |  |  | 	"BCME_NONRESIDENT", | 
					
						
							|  |  |  | 	"BCME_SCANREJECT", | 
					
						
							|  |  |  | 	"BCME_USAGE_ERROR", | 
					
						
							|  |  |  | 	"BCME_IOCTL_ERROR", | 
					
						
							|  |  |  | 	"BCME_SERIAL_PORT_ERR", | 
					
						
							|  |  |  | 	"BCME_DISABLED", | 
					
						
							|  |  |  | 	"BCME_DECERR", | 
					
						
							|  |  |  | 	"BCME_ENCERR", | 
					
						
							|  |  |  | 	"BCME_MICERR", | 
					
						
							|  |  |  | 	"BCME_REPLAY", | 
					
						
							|  |  |  | 	"BCME_IE_NOTFOUND", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *brcmf_fil_get_errstr(u32 err) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (err >= ARRAY_SIZE(brcmf_fil_errstr)) | 
					
						
							|  |  |  | 		return "(unknown)"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return brcmf_fil_errstr[err]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | static const char *brcmf_fil_get_errstr(u32 err) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ""; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* DEBUG */
 | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | static s32 | 
					
						
							|  |  |  | brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = ifp->drvr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 20:31:35 +01:00
										 |  |  | 	if (drvr->bus_if->state != BRCMF_BUS_UP) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("bus is down. we have nothing to do.\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 		return -EIO; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (data != NULL) | 
					
						
							|  |  |  | 		len = min_t(uint, len, BRCMF_DCMD_MAXLEN); | 
					
						
							|  |  |  | 	if (set) | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:16 +01:00
										 |  |  | 		err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2013-11-29 12:25:16 +01:00
										 |  |  | 		err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (err >= 0) | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:09 +01:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-28 14:56:09 +01:00
										 |  |  | 	brcmf_dbg(FIL, "Failed: %s (%d)\n", | 
					
						
							|  |  |  | 		  brcmf_fil_get_errstr((u32)(-err)), err); | 
					
						
							|  |  |  | 	return -EBADE; | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = brcmf_fil_cmd_data(ifp, cmd, data, len, true); | 
					
						
							|  |  |  | 	mutex_unlock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 	err = brcmf_fil_cmd_data(ifp, cmd, data, len, false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&ifp->drvr->proto_block); | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, data); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true); | 
					
						
							|  |  |  | 	mutex_unlock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(*data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false); | 
					
						
							|  |  |  | 	mutex_unlock(&ifp->drvr->proto_block); | 
					
						
							|  |  |  | 	*data = le32_to_cpu(data_le); | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static u32 | 
					
						
							| 
									
										
										
										
											2014-01-15 14:55:59 +01:00
										 |  |  | brcmf_create_iovar(char *name, const char *data, u32 datalen, | 
					
						
							|  |  |  | 		   char *buf, u32 buflen) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	u32 len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = strlen(name) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((len + datalen) > buflen) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(buf, name, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* append data onto the end of the name string */ | 
					
						
							|  |  |  | 	if (data && datalen) | 
					
						
							|  |  |  | 		memcpy(&buf[len], data, datalen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return len + datalen; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2014-01-15 14:55:59 +01:00
										 |  |  | brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 			 u32 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = ifp->drvr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	u32 buflen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | 
					
						
							|  |  |  | 				    sizeof(drvr->proto_buf)); | 
					
						
							|  |  |  | 	if (buflen) { | 
					
						
							|  |  |  | 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | 
					
						
							|  |  |  | 					 buflen, true); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = -EPERM; | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Creating iovar failed\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&drvr->proto_block); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 			 u32 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = ifp->drvr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	u32 buflen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | 
					
						
							|  |  |  | 				    sizeof(drvr->proto_buf)); | 
					
						
							|  |  |  | 	if (buflen) { | 
					
						
							|  |  |  | 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | 
					
						
							|  |  |  | 					 buflen, false); | 
					
						
							|  |  |  | 		if (err == 0) | 
					
						
							|  |  |  | 			memcpy(data, drvr->proto_buf, len); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = -EPERM; | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Creating iovar failed\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&drvr->proto_block); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | 	return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le)); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(*data); | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | 	err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le)); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	if (err == 0) | 
					
						
							|  |  |  | 		*data = le32_to_cpu(data_le); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static u32 | 
					
						
							|  |  |  | brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf, | 
					
						
							|  |  |  | 		    u32 buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const s8 *prefix = "bsscfg:"; | 
					
						
							|  |  |  | 	s8 *p; | 
					
						
							|  |  |  | 	u32 prefixlen; | 
					
						
							|  |  |  | 	u32 namelen; | 
					
						
							|  |  |  | 	u32 iolen; | 
					
						
							|  |  |  | 	__le32 bssidx_le; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bssidx == 0) | 
					
						
							|  |  |  | 		return brcmf_create_iovar(name, data, datalen, buf, buflen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prefixlen = strlen(prefix); | 
					
						
							|  |  |  | 	namelen = strlen(name) + 1; /* lengh of iovar  name + null */ | 
					
						
							|  |  |  | 	iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (buflen < iolen) { | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("buffer is too short\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy prefix, no null */ | 
					
						
							|  |  |  | 	memcpy(p, prefix, prefixlen); | 
					
						
							|  |  |  | 	p += prefixlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy iovar name including null */ | 
					
						
							|  |  |  | 	memcpy(p, name, namelen); | 
					
						
							|  |  |  | 	p += namelen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* bss config index as first data */ | 
					
						
							|  |  |  | 	bssidx_le = cpu_to_le32(bssidx); | 
					
						
							|  |  |  | 	memcpy(p, &bssidx_le, sizeof(bssidx_le)); | 
					
						
							|  |  |  | 	p += sizeof(bssidx_le); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* parameter buffer follows */ | 
					
						
							|  |  |  | 	if (datalen) | 
					
						
							|  |  |  | 		memcpy(p, data, datalen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return iolen; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 			  void *data, u32 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = ifp->drvr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	u32 buflen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx, | 
					
						
							|  |  |  | 		  ifp->bssidx, name, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:21 -07:00
										 |  |  | 	buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, | 
					
						
							|  |  |  | 				     drvr->proto_buf, sizeof(drvr->proto_buf)); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	if (buflen) { | 
					
						
							|  |  |  | 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | 
					
						
							|  |  |  | 					 buflen, true); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = -EPERM; | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Creating bsscfg failed\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&drvr->proto_block); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 			  void *data, u32 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct brcmf_pub *drvr = ifp->drvr; | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 	u32 buflen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&drvr->proto_block); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-05 16:22:21 -08:00
										 |  |  | 	buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:21 -07:00
										 |  |  | 				     drvr->proto_buf, sizeof(drvr->proto_buf)); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	if (buflen) { | 
					
						
							|  |  |  | 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | 
					
						
							|  |  |  | 					 buflen, false); | 
					
						
							|  |  |  | 		if (err == 0) | 
					
						
							|  |  |  | 			memcpy(data, drvr->proto_buf, len); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = -EPERM; | 
					
						
							| 
									
										
										
										
											2012-12-07 10:49:57 +01:00
										 |  |  | 		brcmf_err("Creating bsscfg failed\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-03 21:05:32 +01:00
										 |  |  | 	brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx, | 
					
						
							|  |  |  | 		  ifp->bssidx, name, len); | 
					
						
							| 
									
										
										
										
											2012-11-14 18:46:22 -08:00
										 |  |  | 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 
					
						
							| 
									
										
										
										
											2013-12-12 11:59:01 +01:00
										 |  |  | 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&drvr->proto_block); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | 	return brcmf_fil_bsscfg_data_set(ifp, name, &data_le, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 					 sizeof(data_le)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s32 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	__le32 data_le = cpu_to_le32(*data); | 
					
						
							|  |  |  | 	s32 err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:23 -07:00
										 |  |  | 	err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le, | 
					
						
							| 
									
										
										
										
											2012-10-22 10:36:14 -07:00
										 |  |  | 					sizeof(data_le)); | 
					
						
							|  |  |  | 	if (err == 0) | 
					
						
							|  |  |  | 		*data = le32_to_cpu(data_le); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } |