xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: ISC
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2012 Broadcom Corporation
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun /* FWIL is the Firmware Interface Layer. In this module the support functions
7*4882a593Smuzhiyun  * are located to set and get variables to and from the firmware.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/netdevice.h>
12*4882a593Smuzhiyun #include <brcmu_utils.h>
13*4882a593Smuzhiyun #include <brcmu_wifi.h>
14*4882a593Smuzhiyun #include "core.h"
15*4882a593Smuzhiyun #include "bus.h"
16*4882a593Smuzhiyun #include "debug.h"
17*4882a593Smuzhiyun #include "tracepoint.h"
18*4882a593Smuzhiyun #include "fwil.h"
19*4882a593Smuzhiyun #include "proto.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define MAX_HEX_DUMP_LEN	64
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #ifdef DEBUG
25*4882a593Smuzhiyun static const char * const brcmf_fil_errstr[] = {
26*4882a593Smuzhiyun 	"BCME_OK",
27*4882a593Smuzhiyun 	"BCME_ERROR",
28*4882a593Smuzhiyun 	"BCME_BADARG",
29*4882a593Smuzhiyun 	"BCME_BADOPTION",
30*4882a593Smuzhiyun 	"BCME_NOTUP",
31*4882a593Smuzhiyun 	"BCME_NOTDOWN",
32*4882a593Smuzhiyun 	"BCME_NOTAP",
33*4882a593Smuzhiyun 	"BCME_NOTSTA",
34*4882a593Smuzhiyun 	"BCME_BADKEYIDX",
35*4882a593Smuzhiyun 	"BCME_RADIOOFF",
36*4882a593Smuzhiyun 	"BCME_NOTBANDLOCKED",
37*4882a593Smuzhiyun 	"BCME_NOCLK",
38*4882a593Smuzhiyun 	"BCME_BADRATESET",
39*4882a593Smuzhiyun 	"BCME_BADBAND",
40*4882a593Smuzhiyun 	"BCME_BUFTOOSHORT",
41*4882a593Smuzhiyun 	"BCME_BUFTOOLONG",
42*4882a593Smuzhiyun 	"BCME_BUSY",
43*4882a593Smuzhiyun 	"BCME_NOTASSOCIATED",
44*4882a593Smuzhiyun 	"BCME_BADSSIDLEN",
45*4882a593Smuzhiyun 	"BCME_OUTOFRANGECHAN",
46*4882a593Smuzhiyun 	"BCME_BADCHAN",
47*4882a593Smuzhiyun 	"BCME_BADADDR",
48*4882a593Smuzhiyun 	"BCME_NORESOURCE",
49*4882a593Smuzhiyun 	"BCME_UNSUPPORTED",
50*4882a593Smuzhiyun 	"BCME_BADLEN",
51*4882a593Smuzhiyun 	"BCME_NOTREADY",
52*4882a593Smuzhiyun 	"BCME_EPERM",
53*4882a593Smuzhiyun 	"BCME_NOMEM",
54*4882a593Smuzhiyun 	"BCME_ASSOCIATED",
55*4882a593Smuzhiyun 	"BCME_RANGE",
56*4882a593Smuzhiyun 	"BCME_NOTFOUND",
57*4882a593Smuzhiyun 	"BCME_WME_NOT_ENABLED",
58*4882a593Smuzhiyun 	"BCME_TSPEC_NOTFOUND",
59*4882a593Smuzhiyun 	"BCME_ACM_NOTSUPPORTED",
60*4882a593Smuzhiyun 	"BCME_NOT_WME_ASSOCIATION",
61*4882a593Smuzhiyun 	"BCME_SDIO_ERROR",
62*4882a593Smuzhiyun 	"BCME_DONGLE_DOWN",
63*4882a593Smuzhiyun 	"BCME_VERSION",
64*4882a593Smuzhiyun 	"BCME_TXFAIL",
65*4882a593Smuzhiyun 	"BCME_RXFAIL",
66*4882a593Smuzhiyun 	"BCME_NODEVICE",
67*4882a593Smuzhiyun 	"BCME_NMODE_DISABLED",
68*4882a593Smuzhiyun 	"BCME_NONRESIDENT",
69*4882a593Smuzhiyun 	"BCME_SCANREJECT",
70*4882a593Smuzhiyun 	"BCME_USAGE_ERROR",
71*4882a593Smuzhiyun 	"BCME_IOCTL_ERROR",
72*4882a593Smuzhiyun 	"BCME_SERIAL_PORT_ERR",
73*4882a593Smuzhiyun 	"BCME_DISABLED",
74*4882a593Smuzhiyun 	"BCME_DECERR",
75*4882a593Smuzhiyun 	"BCME_ENCERR",
76*4882a593Smuzhiyun 	"BCME_MICERR",
77*4882a593Smuzhiyun 	"BCME_REPLAY",
78*4882a593Smuzhiyun 	"BCME_IE_NOTFOUND",
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun 
brcmf_fil_get_errstr(u32 err)81*4882a593Smuzhiyun static const char *brcmf_fil_get_errstr(u32 err)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	if (err >= ARRAY_SIZE(brcmf_fil_errstr))
84*4882a593Smuzhiyun 		return "(unknown)";
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	return brcmf_fil_errstr[err];
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun #else
brcmf_fil_get_errstr(u32 err)89*4882a593Smuzhiyun static const char *brcmf_fil_get_errstr(u32 err)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	return "";
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun #endif /* DEBUG */
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun static s32
brcmf_fil_cmd_data(struct brcmf_if * ifp,u32 cmd,void * data,u32 len,bool set)96*4882a593Smuzhiyun brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	struct brcmf_pub *drvr = ifp->drvr;
99*4882a593Smuzhiyun 	s32 err, fwerr;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (drvr->bus_if->state != BRCMF_BUS_UP) {
102*4882a593Smuzhiyun 		bphy_err(drvr, "bus is down. we have nothing to do.\n");
103*4882a593Smuzhiyun 		return -EIO;
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	if (data != NULL)
107*4882a593Smuzhiyun 		len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
108*4882a593Smuzhiyun 	if (set)
109*4882a593Smuzhiyun 		err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
110*4882a593Smuzhiyun 					   data, len, &fwerr);
111*4882a593Smuzhiyun 	else
112*4882a593Smuzhiyun 		err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
113*4882a593Smuzhiyun 					     data, len, &fwerr);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	if (err) {
116*4882a593Smuzhiyun 		brcmf_dbg(FIL, "Failed: error=%d\n", err);
117*4882a593Smuzhiyun 	} else if (fwerr < 0) {
118*4882a593Smuzhiyun 		brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
119*4882a593Smuzhiyun 			  brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
120*4882a593Smuzhiyun 		err = -EBADE;
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun 	if (ifp->fwil_fwerr)
123*4882a593Smuzhiyun 		return fwerr;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	return err;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun s32
brcmf_fil_cmd_data_set(struct brcmf_if * ifp,u32 cmd,void * data,u32 len)129*4882a593Smuzhiyun brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	s32 err;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	mutex_lock(&ifp->drvr->proto_block);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
136*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
137*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
140*4882a593Smuzhiyun 	mutex_unlock(&ifp->drvr->proto_block);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	return err;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun s32
brcmf_fil_cmd_data_get(struct brcmf_if * ifp,u32 cmd,void * data,u32 len)146*4882a593Smuzhiyun brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	s32 err;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	mutex_lock(&ifp->drvr->proto_block);
151*4882a593Smuzhiyun 	err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
154*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
155*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	mutex_unlock(&ifp->drvr->proto_block);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	return err;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun s32
brcmf_fil_cmd_int_set(struct brcmf_if * ifp,u32 cmd,u32 data)164*4882a593Smuzhiyun brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	s32 err;
167*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(data);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	mutex_lock(&ifp->drvr->proto_block);
170*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, data);
171*4882a593Smuzhiyun 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
172*4882a593Smuzhiyun 	mutex_unlock(&ifp->drvr->proto_block);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	return err;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun s32
brcmf_fil_cmd_int_get(struct brcmf_if * ifp,u32 cmd,u32 * data)178*4882a593Smuzhiyun brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	s32 err;
181*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(*data);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	mutex_lock(&ifp->drvr->proto_block);
184*4882a593Smuzhiyun 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
185*4882a593Smuzhiyun 	mutex_unlock(&ifp->drvr->proto_block);
186*4882a593Smuzhiyun 	*data = le32_to_cpu(data_le);
187*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return err;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static u32
brcmf_create_iovar(char * name,const char * data,u32 datalen,char * buf,u32 buflen)193*4882a593Smuzhiyun brcmf_create_iovar(char *name, const char *data, u32 datalen,
194*4882a593Smuzhiyun 		   char *buf, u32 buflen)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	u32 len;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	len = strlen(name) + 1;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if ((len + datalen) > buflen)
201*4882a593Smuzhiyun 		return 0;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	memcpy(buf, name, len);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* append data onto the end of the name string */
206*4882a593Smuzhiyun 	if (data && datalen)
207*4882a593Smuzhiyun 		memcpy(&buf[len], data, datalen);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return len + datalen;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun s32
brcmf_fil_iovar_data_set(struct brcmf_if * ifp,char * name,const void * data,u32 len)214*4882a593Smuzhiyun brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
215*4882a593Smuzhiyun 			 u32 len)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct brcmf_pub *drvr = ifp->drvr;
218*4882a593Smuzhiyun 	s32 err;
219*4882a593Smuzhiyun 	u32 buflen;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	mutex_lock(&drvr->proto_block);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
224*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
225*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
228*4882a593Smuzhiyun 				    sizeof(drvr->proto_buf));
229*4882a593Smuzhiyun 	if (buflen) {
230*4882a593Smuzhiyun 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
231*4882a593Smuzhiyun 					 buflen, true);
232*4882a593Smuzhiyun 	} else {
233*4882a593Smuzhiyun 		err = -EPERM;
234*4882a593Smuzhiyun 		bphy_err(drvr, "Creating iovar failed\n");
235*4882a593Smuzhiyun 	}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	mutex_unlock(&drvr->proto_block);
238*4882a593Smuzhiyun 	return err;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun s32
brcmf_fil_iovar_data_get(struct brcmf_if * ifp,char * name,void * data,u32 len)242*4882a593Smuzhiyun brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
243*4882a593Smuzhiyun 			 u32 len)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	struct brcmf_pub *drvr = ifp->drvr;
246*4882a593Smuzhiyun 	s32 err;
247*4882a593Smuzhiyun 	u32 buflen;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	mutex_lock(&drvr->proto_block);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
252*4882a593Smuzhiyun 				    sizeof(drvr->proto_buf));
253*4882a593Smuzhiyun 	if (buflen) {
254*4882a593Smuzhiyun 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
255*4882a593Smuzhiyun 					 buflen, false);
256*4882a593Smuzhiyun 		if (err == 0)
257*4882a593Smuzhiyun 			memcpy(data, drvr->proto_buf, len);
258*4882a593Smuzhiyun 	} else {
259*4882a593Smuzhiyun 		err = -EPERM;
260*4882a593Smuzhiyun 		bphy_err(drvr, "Creating iovar failed\n");
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
264*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
265*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	mutex_unlock(&drvr->proto_block);
268*4882a593Smuzhiyun 	return err;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun s32
brcmf_fil_iovar_int_set(struct brcmf_if * ifp,char * name,u32 data)272*4882a593Smuzhiyun brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(data);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun s32
brcmf_fil_iovar_int_get(struct brcmf_if * ifp,char * name,u32 * data)280*4882a593Smuzhiyun brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(*data);
283*4882a593Smuzhiyun 	s32 err;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
286*4882a593Smuzhiyun 	if (err == 0)
287*4882a593Smuzhiyun 		*data = le32_to_cpu(data_le);
288*4882a593Smuzhiyun 	return err;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun static u32
brcmf_create_bsscfg(s32 bsscfgidx,char * name,char * data,u32 datalen,char * buf,u32 buflen)292*4882a593Smuzhiyun brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen,
293*4882a593Smuzhiyun 		    char *buf, u32 buflen)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	const s8 *prefix = "bsscfg:";
296*4882a593Smuzhiyun 	s8 *p;
297*4882a593Smuzhiyun 	u32 prefixlen;
298*4882a593Smuzhiyun 	u32 namelen;
299*4882a593Smuzhiyun 	u32 iolen;
300*4882a593Smuzhiyun 	__le32 bsscfgidx_le;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (bsscfgidx == 0)
303*4882a593Smuzhiyun 		return brcmf_create_iovar(name, data, datalen, buf, buflen);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	prefixlen = strlen(prefix);
306*4882a593Smuzhiyun 	namelen = strlen(name) + 1; /* length of iovar  name + null */
307*4882a593Smuzhiyun 	iolen = prefixlen + namelen + sizeof(bsscfgidx_le) + datalen;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	if (buflen < iolen) {
310*4882a593Smuzhiyun 		brcmf_err("buffer is too short\n");
311*4882a593Smuzhiyun 		return 0;
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	p = buf;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	/* copy prefix, no null */
317*4882a593Smuzhiyun 	memcpy(p, prefix, prefixlen);
318*4882a593Smuzhiyun 	p += prefixlen;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	/* copy iovar name including null */
321*4882a593Smuzhiyun 	memcpy(p, name, namelen);
322*4882a593Smuzhiyun 	p += namelen;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	/* bss config index as first data */
325*4882a593Smuzhiyun 	bsscfgidx_le = cpu_to_le32(bsscfgidx);
326*4882a593Smuzhiyun 	memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
327*4882a593Smuzhiyun 	p += sizeof(bsscfgidx_le);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* parameter buffer follows */
330*4882a593Smuzhiyun 	if (datalen)
331*4882a593Smuzhiyun 		memcpy(p, data, datalen);
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	return iolen;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun s32
brcmf_fil_bsscfg_data_set(struct brcmf_if * ifp,char * name,void * data,u32 len)337*4882a593Smuzhiyun brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
338*4882a593Smuzhiyun 			  void *data, u32 len)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	struct brcmf_pub *drvr = ifp->drvr;
341*4882a593Smuzhiyun 	s32 err;
342*4882a593Smuzhiyun 	u32 buflen;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	mutex_lock(&drvr->proto_block);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
347*4882a593Smuzhiyun 		  ifp->bsscfgidx, name, len);
348*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
349*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
352*4882a593Smuzhiyun 				     drvr->proto_buf, sizeof(drvr->proto_buf));
353*4882a593Smuzhiyun 	if (buflen) {
354*4882a593Smuzhiyun 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
355*4882a593Smuzhiyun 					 buflen, true);
356*4882a593Smuzhiyun 	} else {
357*4882a593Smuzhiyun 		err = -EPERM;
358*4882a593Smuzhiyun 		bphy_err(drvr, "Creating bsscfg failed\n");
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	mutex_unlock(&drvr->proto_block);
362*4882a593Smuzhiyun 	return err;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun s32
brcmf_fil_bsscfg_data_get(struct brcmf_if * ifp,char * name,void * data,u32 len)366*4882a593Smuzhiyun brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
367*4882a593Smuzhiyun 			  void *data, u32 len)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	struct brcmf_pub *drvr = ifp->drvr;
370*4882a593Smuzhiyun 	s32 err;
371*4882a593Smuzhiyun 	u32 buflen;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	mutex_lock(&drvr->proto_block);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
376*4882a593Smuzhiyun 				     drvr->proto_buf, sizeof(drvr->proto_buf));
377*4882a593Smuzhiyun 	if (buflen) {
378*4882a593Smuzhiyun 		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
379*4882a593Smuzhiyun 					 buflen, false);
380*4882a593Smuzhiyun 		if (err == 0)
381*4882a593Smuzhiyun 			memcpy(data, drvr->proto_buf, len);
382*4882a593Smuzhiyun 	} else {
383*4882a593Smuzhiyun 		err = -EPERM;
384*4882a593Smuzhiyun 		bphy_err(drvr, "Creating bsscfg failed\n");
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 	brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
387*4882a593Smuzhiyun 		  ifp->bsscfgidx, name, len);
388*4882a593Smuzhiyun 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
389*4882a593Smuzhiyun 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	mutex_unlock(&drvr->proto_block);
392*4882a593Smuzhiyun 	return err;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun s32
brcmf_fil_bsscfg_int_set(struct brcmf_if * ifp,char * name,u32 data)397*4882a593Smuzhiyun brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(data);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
402*4882a593Smuzhiyun 					 sizeof(data_le));
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun s32
brcmf_fil_bsscfg_int_get(struct brcmf_if * ifp,char * name,u32 * data)406*4882a593Smuzhiyun brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	__le32 data_le = cpu_to_le32(*data);
409*4882a593Smuzhiyun 	s32 err;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
412*4882a593Smuzhiyun 					sizeof(data_le));
413*4882a593Smuzhiyun 	if (err == 0)
414*4882a593Smuzhiyun 		*data = le32_to_cpu(data_le);
415*4882a593Smuzhiyun 	return err;
416*4882a593Smuzhiyun }
417