root/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. brcmf_fil_get_errstr
  2. brcmf_fil_get_errstr
  3. brcmf_fil_cmd_data
  4. brcmf_fil_cmd_data_set
  5. brcmf_fil_cmd_data_get
  6. brcmf_fil_cmd_int_set
  7. brcmf_fil_cmd_int_get
  8. brcmf_create_iovar
  9. brcmf_fil_iovar_data_set
  10. brcmf_fil_iovar_data_get
  11. brcmf_fil_iovar_int_set
  12. brcmf_fil_iovar_int_get
  13. brcmf_create_bsscfg
  14. brcmf_fil_bsscfg_data_set
  15. brcmf_fil_bsscfg_data_get
  16. brcmf_fil_bsscfg_int_set
  17. brcmf_fil_bsscfg_int_get

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

/* [<][>][^][v][top][bottom][index][help] */