0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/string.h>
0008 #include <linux/netdevice.h>
0009 #include <linux/module.h>
0010 #include <linux/firmware.h>
0011 #include <brcmu_wifi.h>
0012 #include <brcmu_utils.h>
0013 #include "core.h"
0014 #include "bus.h"
0015 #include "debug.h"
0016 #include "fwil.h"
0017 #include "fwil_types.h"
0018 #include "tracepoint.h"
0019 #include "common.h"
0020 #include "of.h"
0021 #include "firmware.h"
0022 #include "chip.h"
0023
0024 MODULE_AUTHOR("Broadcom Corporation");
0025 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
0026 MODULE_LICENSE("Dual BSD/GPL");
0027
0028 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
0029 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
0030
0031
0032 #define BRCMF_JOIN_PREF_RSSI_BOOST 8
0033
0034 #define BRCMF_DEFAULT_TXGLOM_SIZE 32
0035
0036 static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
0037 module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
0038 MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]");
0039
0040
0041 int brcmf_msg_level;
0042 module_param_named(debug, brcmf_msg_level, int, 0600);
0043 MODULE_PARM_DESC(debug, "Level of debug output");
0044
0045 static int brcmf_p2p_enable;
0046 module_param_named(p2pon, brcmf_p2p_enable, int, 0);
0047 MODULE_PARM_DESC(p2pon, "Enable legacy p2p management functionality");
0048
0049 static int brcmf_feature_disable;
0050 module_param_named(feature_disable, brcmf_feature_disable, int, 0);
0051 MODULE_PARM_DESC(feature_disable, "Disable features");
0052
0053 static char brcmf_firmware_path[BRCMF_FW_ALTPATH_LEN];
0054 module_param_string(alternative_fw_path, brcmf_firmware_path,
0055 BRCMF_FW_ALTPATH_LEN, 0400);
0056 MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path");
0057
0058 static int brcmf_fcmode;
0059 module_param_named(fcmode, brcmf_fcmode, int, 0);
0060 MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
0061
0062 static int brcmf_roamoff;
0063 module_param_named(roamoff, brcmf_roamoff, int, 0400);
0064 MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
0065
0066 static int brcmf_iapp_enable;
0067 module_param_named(iapp, brcmf_iapp_enable, int, 0);
0068 MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
0069
0070 #ifdef DEBUG
0071
0072 static int brcmf_ignore_probe_fail;
0073 module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0);
0074 MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
0075 #endif
0076
0077 static struct brcmfmac_platform_data *brcmfmac_pdata;
0078 struct brcmf_mp_global_t brcmf_mp_global;
0079
0080 void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
0081 {
0082 struct brcmf_pub *drvr = ifp->drvr;
0083 struct brcmf_join_pref_params join_pref_params[2];
0084 int err;
0085
0086
0087 join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
0088 join_pref_params[0].len = 2;
0089 join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
0090 join_pref_params[0].band = WLC_BAND_5G;
0091
0092 join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
0093 join_pref_params[1].len = 2;
0094 join_pref_params[1].rssi_gain = 0;
0095 join_pref_params[1].band = 0;
0096 err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
0097 sizeof(join_pref_params));
0098 if (err)
0099 bphy_err(drvr, "Set join_pref error (%d)\n", err);
0100 }
0101
0102 static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
0103 struct brcmf_dload_data_le *dload_buf,
0104 u32 len)
0105 {
0106 s32 err;
0107
0108 flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
0109 dload_buf->flag = cpu_to_le16(flag);
0110 dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM);
0111 dload_buf->len = cpu_to_le32(len);
0112 dload_buf->crc = cpu_to_le32(0);
0113 len = sizeof(*dload_buf) + len - 1;
0114
0115 err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len);
0116
0117 return err;
0118 }
0119
0120 static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
0121 {
0122 struct brcmf_pub *drvr = ifp->drvr;
0123 struct brcmf_bus *bus = drvr->bus_if;
0124 struct brcmf_dload_data_le *chunk_buf;
0125 const struct firmware *clm = NULL;
0126 u8 clm_name[BRCMF_FW_NAME_LEN];
0127 u32 chunk_len;
0128 u32 datalen;
0129 u32 cumulative_len;
0130 u16 dl_flag = DL_BEGIN;
0131 u32 status;
0132 s32 err;
0133
0134 brcmf_dbg(TRACE, "Enter\n");
0135
0136 memset(clm_name, 0, sizeof(clm_name));
0137 err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
0138 if (err) {
0139 bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
0140 return err;
0141 }
0142
0143 err = firmware_request_nowarn(&clm, clm_name, bus->dev);
0144 if (err) {
0145 brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
0146 err);
0147 return 0;
0148 }
0149
0150 chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
0151 if (!chunk_buf) {
0152 err = -ENOMEM;
0153 goto done;
0154 }
0155
0156 datalen = clm->size;
0157 cumulative_len = 0;
0158 do {
0159 if (datalen > MAX_CHUNK_LEN) {
0160 chunk_len = MAX_CHUNK_LEN;
0161 } else {
0162 chunk_len = datalen;
0163 dl_flag |= DL_END;
0164 }
0165 memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
0166
0167 err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
0168
0169 dl_flag &= ~DL_BEGIN;
0170
0171 cumulative_len += chunk_len;
0172 datalen -= chunk_len;
0173 } while ((datalen > 0) && (err == 0));
0174
0175 if (err) {
0176 bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n",
0177 clm->size, err);
0178
0179 err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
0180 if (err)
0181 bphy_err(drvr, "get clmload_status failed (%d)\n", err);
0182 else
0183 brcmf_dbg(INFO, "clmload_status=%d\n", status);
0184 err = -EIO;
0185 }
0186
0187 kfree(chunk_buf);
0188 done:
0189 release_firmware(clm);
0190 return err;
0191 }
0192
0193 int brcmf_c_set_cur_etheraddr(struct brcmf_if *ifp, const u8 *addr)
0194 {
0195 s32 err;
0196
0197 err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", addr, ETH_ALEN);
0198 if (err < 0)
0199 bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err);
0200
0201 return err;
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 static const u8 brcmf_default_mac_address[ETH_ALEN] = {
0215 0x00, 0x90, 0x4c, 0xc5, 0x12, 0x38
0216 };
0217
0218 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
0219 {
0220 struct brcmf_pub *drvr = ifp->drvr;
0221 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
0222 u8 buf[BRCMF_DCMD_SMLEN];
0223 struct brcmf_bus *bus;
0224 struct brcmf_rev_info_le revinfo;
0225 struct brcmf_rev_info *ri;
0226 char *clmver;
0227 char *ptr;
0228 s32 err;
0229
0230 if (is_valid_ether_addr(ifp->mac_addr)) {
0231
0232 err = brcmf_c_set_cur_etheraddr(ifp, ifp->mac_addr);
0233 if (err < 0)
0234 goto done;
0235 } else {
0236
0237 err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
0238 sizeof(ifp->mac_addr));
0239 if (err < 0) {
0240 bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
0241 goto done;
0242 }
0243
0244 if (ether_addr_equal_unaligned(ifp->mac_addr, brcmf_default_mac_address)) {
0245 bphy_err(drvr, "Default MAC is used, replacing with random MAC to avoid conflicts\n");
0246 eth_random_addr(ifp->mac_addr);
0247 ifp->ndev->addr_assign_type = NET_ADDR_RANDOM;
0248 err = brcmf_c_set_cur_etheraddr(ifp, ifp->mac_addr);
0249 if (err < 0)
0250 goto done;
0251 }
0252 }
0253
0254 memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
0255 memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
0256
0257 bus = ifp->drvr->bus_if;
0258 ri = &ifp->drvr->revinfo;
0259
0260 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
0261 &revinfo, sizeof(revinfo));
0262 if (err < 0) {
0263 bphy_err(drvr, "retrieving revision info failed, %d\n", err);
0264 strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
0265 } else {
0266 ri->vendorid = le32_to_cpu(revinfo.vendorid);
0267 ri->deviceid = le32_to_cpu(revinfo.deviceid);
0268 ri->radiorev = le32_to_cpu(revinfo.radiorev);
0269 ri->corerev = le32_to_cpu(revinfo.corerev);
0270 ri->boardid = le32_to_cpu(revinfo.boardid);
0271 ri->boardvendor = le32_to_cpu(revinfo.boardvendor);
0272 ri->boardrev = le32_to_cpu(revinfo.boardrev);
0273 ri->driverrev = le32_to_cpu(revinfo.driverrev);
0274 ri->ucoderev = le32_to_cpu(revinfo.ucoderev);
0275 ri->bus = le32_to_cpu(revinfo.bus);
0276 ri->phytype = le32_to_cpu(revinfo.phytype);
0277 ri->phyrev = le32_to_cpu(revinfo.phyrev);
0278 ri->anarev = le32_to_cpu(revinfo.anarev);
0279 ri->chippkg = le32_to_cpu(revinfo.chippkg);
0280 ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
0281
0282
0283 if (!bus->chip) {
0284 bus->chip = le32_to_cpu(revinfo.chipnum);
0285 bus->chiprev = le32_to_cpu(revinfo.chiprev);
0286 }
0287 }
0288 ri->result = err;
0289
0290 if (bus->chip)
0291 brcmf_chip_name(bus->chip, bus->chiprev,
0292 ri->chipname, sizeof(ri->chipname));
0293
0294
0295 err = brcmf_c_process_clm_blob(ifp);
0296 if (err < 0) {
0297 bphy_err(drvr, "download CLM blob file failed, %d\n", err);
0298 goto done;
0299 }
0300
0301
0302 memset(buf, 0, sizeof(buf));
0303 err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
0304 if (err < 0) {
0305 bphy_err(drvr, "Retrieving version information failed, %d\n",
0306 err);
0307 goto done;
0308 }
0309 ptr = (char *)buf;
0310 strsep(&ptr, "\n");
0311
0312
0313 brcmf_info("Firmware: %s %s\n", ri->chipname, buf);
0314
0315
0316 ptr = strrchr(buf, ' ') + 1;
0317 strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
0318
0319
0320 memset(buf, 0, sizeof(buf));
0321 err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
0322 if (err) {
0323 brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
0324 } else {
0325 clmver = (char *)buf;
0326
0327 memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
0328
0329
0330
0331
0332 strreplace(clmver, '\n', ' ');
0333
0334 brcmf_dbg(INFO, "CLM version = %s\n", clmver);
0335 }
0336
0337
0338 err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
0339 if (err) {
0340 bphy_err(drvr, "failed setting mpc\n");
0341 goto done;
0342 }
0343
0344 brcmf_c_set_joinpref_default(ifp);
0345
0346
0347 err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
0348 BRCMF_EVENTING_MASK_LEN);
0349 if (err) {
0350 bphy_err(drvr, "Get event_msgs error (%d)\n", err);
0351 goto done;
0352 }
0353 setbit(eventmask, BRCMF_E_IF);
0354 err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
0355 BRCMF_EVENTING_MASK_LEN);
0356 if (err) {
0357 bphy_err(drvr, "Set event_msgs error (%d)\n", err);
0358 goto done;
0359 }
0360
0361
0362 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
0363 BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
0364 if (err) {
0365 bphy_err(drvr, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
0366 err);
0367 goto done;
0368 }
0369
0370
0371 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
0372 BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
0373 if (err) {
0374 bphy_err(drvr, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
0375 err);
0376 goto done;
0377 }
0378
0379
0380 (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
0381 done:
0382 return err;
0383 }
0384
0385 #ifndef CONFIG_BRCM_TRACING
0386 void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...)
0387 {
0388 struct va_format vaf;
0389 va_list args;
0390
0391 va_start(args, fmt);
0392
0393 vaf.fmt = fmt;
0394 vaf.va = &args;
0395 if (bus)
0396 dev_err(bus->dev, "%s: %pV", func, &vaf);
0397 else
0398 pr_err("%s: %pV", func, &vaf);
0399
0400 va_end(args);
0401 }
0402 #endif
0403
0404 #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
0405 void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
0406 {
0407 struct va_format vaf = {
0408 .fmt = fmt,
0409 };
0410 va_list args;
0411
0412 va_start(args, fmt);
0413 vaf.va = &args;
0414 if (brcmf_msg_level & level)
0415 pr_debug("%s %pV", func, &vaf);
0416 trace_brcmf_dbg(level, func, &vaf);
0417 va_end(args);
0418 }
0419 #endif
0420
0421 static void brcmf_mp_attach(void)
0422 {
0423
0424
0425
0426
0427 strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
0428 BRCMF_FW_ALTPATH_LEN);
0429 if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
0430 (brcmf_mp_global.firmware_path[0] == '\0')) {
0431 strlcpy(brcmf_mp_global.firmware_path,
0432 brcmfmac_pdata->fw_alternative_path,
0433 BRCMF_FW_ALTPATH_LEN);
0434 }
0435 }
0436
0437 struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
0438 enum brcmf_bus_type bus_type,
0439 u32 chip, u32 chiprev)
0440 {
0441 struct brcmf_mp_device *settings;
0442 struct brcmfmac_pd_device *device_pd;
0443 bool found;
0444 int i;
0445
0446 brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip,
0447 chiprev);
0448 settings = kzalloc(sizeof(*settings), GFP_ATOMIC);
0449 if (!settings)
0450 return NULL;
0451
0452
0453 settings->p2p_enable = !!brcmf_p2p_enable;
0454 settings->feature_disable = brcmf_feature_disable;
0455 settings->fcmode = brcmf_fcmode;
0456 settings->roamoff = !!brcmf_roamoff;
0457 settings->iapp = !!brcmf_iapp_enable;
0458 #ifdef DEBUG
0459 settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
0460 #endif
0461
0462 if (bus_type == BRCMF_BUSTYPE_SDIO)
0463 settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz;
0464
0465
0466 found = false;
0467 if (brcmfmac_pdata) {
0468 for (i = 0; i < brcmfmac_pdata->device_count; i++) {
0469 device_pd = &brcmfmac_pdata->devices[i];
0470 if ((device_pd->bus_type == bus_type) &&
0471 (device_pd->id == chip) &&
0472 ((device_pd->rev == chiprev) ||
0473 (device_pd->rev == -1))) {
0474 brcmf_dbg(INFO, "Platform data for device found\n");
0475 settings->country_codes =
0476 device_pd->country_codes;
0477 if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
0478 memcpy(&settings->bus.sdio,
0479 &device_pd->bus.sdio,
0480 sizeof(settings->bus.sdio));
0481 found = true;
0482 break;
0483 }
0484 }
0485 }
0486 if (!found) {
0487
0488 brcmf_dmi_probe(settings, chip, chiprev);
0489 brcmf_of_probe(dev, bus_type, settings);
0490 }
0491 return settings;
0492 }
0493
0494 void brcmf_release_module_param(struct brcmf_mp_device *module_param)
0495 {
0496 kfree(module_param);
0497 }
0498
0499 static int __init brcmf_common_pd_probe(struct platform_device *pdev)
0500 {
0501 brcmf_dbg(INFO, "Enter\n");
0502
0503 brcmfmac_pdata = dev_get_platdata(&pdev->dev);
0504
0505 if (brcmfmac_pdata->power_on)
0506 brcmfmac_pdata->power_on();
0507
0508 return 0;
0509 }
0510
0511 static int brcmf_common_pd_remove(struct platform_device *pdev)
0512 {
0513 brcmf_dbg(INFO, "Enter\n");
0514
0515 if (brcmfmac_pdata->power_off)
0516 brcmfmac_pdata->power_off();
0517
0518 return 0;
0519 }
0520
0521 static struct platform_driver brcmf_pd = {
0522 .remove = brcmf_common_pd_remove,
0523 .driver = {
0524 .name = BRCMFMAC_PDATA_NAME,
0525 }
0526 };
0527
0528 static int __init brcmfmac_module_init(void)
0529 {
0530 int err;
0531
0532
0533 err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe);
0534 if (err == -ENODEV)
0535 brcmf_dbg(INFO, "No platform data available.\n");
0536
0537
0538 brcmf_mp_attach();
0539
0540
0541 err = brcmf_core_init();
0542 if (err) {
0543 if (brcmfmac_pdata)
0544 platform_driver_unregister(&brcmf_pd);
0545 }
0546
0547 return err;
0548 }
0549
0550 static void __exit brcmfmac_module_exit(void)
0551 {
0552 brcmf_core_exit();
0553 if (brcmfmac_pdata)
0554 platform_driver_unregister(&brcmf_pd);
0555 }
0556
0557 module_init(brcmfmac_module_init);
0558 module_exit(brcmfmac_module_exit);
0559