1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (c) 2010 Broadcom Corporation 4 */ 5 6 #if defined(__FreeBSD__) 7 #define LINUXKPI_PARAM_PREFIX brcmfmac_ 8 #endif 9 10 #include <linux/kernel.h> 11 #include <linux/string.h> 12 #include <linux/netdevice.h> 13 #include <linux/module.h> 14 #include <linux/firmware.h> 15 #include <brcmu_wifi.h> 16 #include <brcmu_utils.h> 17 #include "core.h" 18 #include "bus.h" 19 #include "debug.h" 20 #include "fwil.h" 21 #include "fwil_types.h" 22 #include "tracepoint.h" 23 #include "common.h" 24 #include "of.h" 25 #include "firmware.h" 26 #include "chip.h" 27 28 MODULE_AUTHOR("Broadcom Corporation"); 29 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); 30 MODULE_LICENSE("Dual BSD/GPL"); 31 #if defined(__FreeBSD__) 32 MODULE_DEPEND(brcmfmac, brcmutil, 1, 1, 1); 33 MODULE_DEPEND(brcmfmac, linuxkpi, 1, 1, 1); 34 MODULE_DEPEND(brcmfmac, linuxkpi_wlan, 1, 1, 1); 35 MODULE_DEPEND(brcmfmac, lindebugfs, 1, 1, 1); /* XXX-BZ someone should fix this */ 36 #endif 37 38 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 39 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 40 41 /* default boost value for RSSI_DELTA in preferred join selection */ 42 #define BRCMF_JOIN_PREF_RSSI_BOOST 8 43 44 #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ 45 46 static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; 47 module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0); 48 MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]"); 49 50 /* Debug level configuration. See debug.h for bits, sysfs modifiable */ 51 int brcmf_msg_level; 52 module_param_named(debug, brcmf_msg_level, int, 0600); 53 MODULE_PARM_DESC(debug, "Level of debug output"); 54 55 static int brcmf_p2p_enable; 56 module_param_named(p2pon, brcmf_p2p_enable, int, 0); 57 MODULE_PARM_DESC(p2pon, "Enable legacy p2p management functionality"); 58 59 static int brcmf_feature_disable; 60 module_param_named(feature_disable, brcmf_feature_disable, int, 0); 61 MODULE_PARM_DESC(feature_disable, "Disable features"); 62 63 static char brcmf_firmware_path[BRCMF_FW_ALTPATH_LEN]; 64 module_param_string(alternative_fw_path, brcmf_firmware_path, 65 BRCMF_FW_ALTPATH_LEN, 0400); 66 MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path"); 67 68 static int brcmf_fcmode; 69 module_param_named(fcmode, brcmf_fcmode, int, 0); 70 MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); 71 72 static int brcmf_roamoff; 73 module_param_named(roamoff, brcmf_roamoff, int, 0400); 74 MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); 75 76 static int brcmf_iapp_enable; 77 module_param_named(iapp, brcmf_iapp_enable, int, 0); 78 MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); 79 80 #ifdef DEBUG 81 /* always succeed brcmf_bus_started() */ 82 static int brcmf_ignore_probe_fail; 83 module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0); 84 MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); 85 #endif 86 87 static struct brcmfmac_platform_data *brcmfmac_pdata; 88 struct brcmf_mp_global_t brcmf_mp_global; 89 90 void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) 91 { 92 struct brcmf_pub *drvr = ifp->drvr; 93 struct brcmf_join_pref_params join_pref_params[2]; 94 int err; 95 96 /* Setup join_pref to select target by RSSI (boost on 5GHz) */ 97 join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; 98 join_pref_params[0].len = 2; 99 join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; 100 join_pref_params[0].band = WLC_BAND_5G; 101 102 join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; 103 join_pref_params[1].len = 2; 104 join_pref_params[1].rssi_gain = 0; 105 join_pref_params[1].band = 0; 106 err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, 107 sizeof(join_pref_params)); 108 if (err) 109 bphy_err(drvr, "Set join_pref error (%d)\n", err); 110 } 111 112 static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, 113 struct brcmf_dload_data_le *dload_buf, 114 u32 len, const char *var) 115 { 116 s32 err; 117 118 flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); 119 dload_buf->flag = cpu_to_le16(flag); 120 dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); 121 dload_buf->len = cpu_to_le32(len); 122 dload_buf->crc = cpu_to_le32(0); 123 124 err = brcmf_fil_iovar_data_set(ifp, var, dload_buf, 125 struct_size(dload_buf, data, len)); 126 127 return err; 128 } 129 130 static int brcmf_c_download_blob(struct brcmf_if *ifp, 131 #if defined(__linux__) 132 const void *data, size_t size, 133 #elif defined(__FreeBSD__) 134 const u8 *data, size_t size, 135 #endif 136 const char *loadvar, const char *statvar) 137 { 138 struct brcmf_pub *drvr = ifp->drvr; 139 struct brcmf_dload_data_le *chunk_buf; 140 u32 chunk_len; 141 u32 datalen; 142 u32 cumulative_len; 143 u16 dl_flag = DL_BEGIN; 144 u32 status; 145 s32 err; 146 147 brcmf_dbg(TRACE, "Enter\n"); 148 149 chunk_buf = kzalloc(struct_size(chunk_buf, data, MAX_CHUNK_LEN), 150 GFP_KERNEL); 151 if (!chunk_buf) { 152 err = -ENOMEM; 153 return -ENOMEM; 154 } 155 156 datalen = size; 157 cumulative_len = 0; 158 do { 159 if (datalen > MAX_CHUNK_LEN) { 160 chunk_len = MAX_CHUNK_LEN; 161 } else { 162 chunk_len = datalen; 163 dl_flag |= DL_END; 164 } 165 memcpy(chunk_buf->data, data + cumulative_len, chunk_len); 166 167 err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len, 168 loadvar); 169 170 dl_flag &= ~DL_BEGIN; 171 172 cumulative_len += chunk_len; 173 datalen -= chunk_len; 174 } while ((datalen > 0) && (err == 0)); 175 176 if (err) { 177 bphy_err(drvr, "%s (%zu byte file) failed (%d)\n", 178 loadvar, size, err); 179 /* Retrieve status and print */ 180 err = brcmf_fil_iovar_int_get(ifp, statvar, &status); 181 if (err) 182 bphy_err(drvr, "get %s failed (%d)\n", statvar, err); 183 else 184 brcmf_dbg(INFO, "%s=%d\n", statvar, status); 185 err = -EIO; 186 } 187 188 kfree(chunk_buf); 189 return err; 190 } 191 192 static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) 193 { 194 struct brcmf_pub *drvr = ifp->drvr; 195 struct brcmf_bus *bus = drvr->bus_if; 196 const struct firmware *fw = NULL; 197 s32 err; 198 199 brcmf_dbg(TRACE, "Enter\n"); 200 201 err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_CLM); 202 if (err || !fw) { 203 brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", 204 err); 205 return 0; 206 } 207 208 err = brcmf_c_download_blob(ifp, fw->data, fw->size, 209 "clmload", "clmload_status"); 210 211 release_firmware(fw); 212 return err; 213 } 214 215 static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp) 216 { 217 struct brcmf_pub *drvr = ifp->drvr; 218 struct brcmf_bus *bus = drvr->bus_if; 219 const struct firmware *fw = NULL; 220 s32 err; 221 222 brcmf_dbg(TRACE, "Enter\n"); 223 224 err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_TXCAP); 225 if (err || !fw) { 226 brcmf_info("no txcap_blob available (err=%d)\n", err); 227 return 0; 228 } 229 230 brcmf_info("TxCap blob found, loading\n"); 231 err = brcmf_c_download_blob(ifp, fw->data, fw->size, 232 "txcapload", "txcapload_status"); 233 234 release_firmware(fw); 235 return err; 236 } 237 238 int brcmf_c_set_cur_etheraddr(struct brcmf_if *ifp, const u8 *addr) 239 { 240 s32 err; 241 242 err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", addr, ETH_ALEN); 243 if (err < 0) 244 bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err); 245 246 return err; 247 } 248 249 /* On some boards there is no eeprom to hold the nvram, in this case instead 250 * a board specific nvram is loaded from /lib/firmware. On most boards the 251 * macaddr setting in the /lib/firmware nvram file is ignored because the 252 * wifibt chip has a unique MAC programmed into the chip itself. 253 * But in some cases the actual MAC from the /lib/firmware nvram file gets 254 * used, leading to MAC conflicts. 255 * The MAC addresses in the troublesome nvram files seem to all come from 256 * the same nvram file template, so we only need to check for 1 known 257 * address to detect this. 258 */ 259 static const u8 brcmf_default_mac_address[ETH_ALEN] = { 260 0x00, 0x90, 0x4c, 0xc5, 0x12, 0x38 261 }; 262 263 static int brcmf_c_process_cal_blob(struct brcmf_if *ifp) 264 { 265 struct brcmf_pub *drvr = ifp->drvr; 266 struct brcmf_mp_device *settings = drvr->settings; 267 s32 err; 268 269 brcmf_dbg(TRACE, "Enter\n"); 270 271 if (!settings->cal_blob || !settings->cal_size) 272 return 0; 273 274 brcmf_info("Calibration blob provided by platform, loading\n"); 275 err = brcmf_c_download_blob(ifp, settings->cal_blob, settings->cal_size, 276 "calload", "calload_status"); 277 return err; 278 } 279 280 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) 281 { 282 struct brcmf_pub *drvr = ifp->drvr; 283 struct brcmf_fweh_info *fweh = drvr->fweh; 284 u8 buf[BRCMF_DCMD_SMLEN]; 285 struct brcmf_bus *bus; 286 struct brcmf_rev_info_le revinfo; 287 struct brcmf_rev_info *ri; 288 char *clmver; 289 char *ptr; 290 s32 err; 291 292 if (is_valid_ether_addr(ifp->mac_addr)) { 293 /* set mac address */ 294 err = brcmf_c_set_cur_etheraddr(ifp, ifp->mac_addr); 295 if (err < 0) 296 goto done; 297 } else { 298 /* retrieve mac address */ 299 err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, 300 sizeof(ifp->mac_addr)); 301 if (err < 0) { 302 bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err); 303 goto done; 304 } 305 306 if (ether_addr_equal_unaligned(ifp->mac_addr, brcmf_default_mac_address)) { 307 bphy_err(drvr, "Default MAC is used, replacing with random MAC to avoid conflicts\n"); 308 eth_random_addr(ifp->mac_addr); 309 ifp->ndev->addr_assign_type = NET_ADDR_RANDOM; 310 err = brcmf_c_set_cur_etheraddr(ifp, ifp->mac_addr); 311 if (err < 0) 312 goto done; 313 } 314 } 315 316 memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); 317 memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN); 318 319 bus = ifp->drvr->bus_if; 320 ri = &ifp->drvr->revinfo; 321 322 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, 323 &revinfo, sizeof(revinfo)); 324 if (err < 0) { 325 bphy_err(drvr, "retrieving revision info failed, %d\n", err); 326 strscpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname)); 327 } else { 328 ri->vendorid = le32_to_cpu(revinfo.vendorid); 329 ri->deviceid = le32_to_cpu(revinfo.deviceid); 330 ri->radiorev = le32_to_cpu(revinfo.radiorev); 331 ri->corerev = le32_to_cpu(revinfo.corerev); 332 ri->boardid = le32_to_cpu(revinfo.boardid); 333 ri->boardvendor = le32_to_cpu(revinfo.boardvendor); 334 ri->boardrev = le32_to_cpu(revinfo.boardrev); 335 ri->driverrev = le32_to_cpu(revinfo.driverrev); 336 ri->ucoderev = le32_to_cpu(revinfo.ucoderev); 337 ri->bus = le32_to_cpu(revinfo.bus); 338 ri->phytype = le32_to_cpu(revinfo.phytype); 339 ri->phyrev = le32_to_cpu(revinfo.phyrev); 340 ri->anarev = le32_to_cpu(revinfo.anarev); 341 ri->chippkg = le32_to_cpu(revinfo.chippkg); 342 ri->nvramrev = le32_to_cpu(revinfo.nvramrev); 343 344 /* use revinfo if not known yet */ 345 if (!bus->chip) { 346 bus->chip = le32_to_cpu(revinfo.chipnum); 347 bus->chiprev = le32_to_cpu(revinfo.chiprev); 348 } 349 } 350 ri->result = err; 351 352 if (bus->chip) 353 brcmf_chip_name(bus->chip, bus->chiprev, 354 ri->chipname, sizeof(ri->chipname)); 355 356 /* Do any CLM downloading */ 357 err = brcmf_c_process_clm_blob(ifp); 358 if (err < 0) { 359 bphy_err(drvr, "download CLM blob file failed, %d\n", err); 360 goto done; 361 } 362 363 /* Do TxCap downloading, if needed */ 364 err = brcmf_c_process_txcap_blob(ifp); 365 if (err < 0) { 366 bphy_err(drvr, "download TxCap blob file failed, %d\n", err); 367 goto done; 368 } 369 370 /* Download external calibration blob, if available */ 371 err = brcmf_c_process_cal_blob(ifp); 372 if (err < 0) { 373 bphy_err(drvr, "download calibration blob file failed, %d\n", err); 374 goto done; 375 } 376 377 /* query for 'ver' to get version info from firmware */ 378 memset(buf, 0, sizeof(buf)); 379 err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); 380 if (err < 0) { 381 bphy_err(drvr, "Retrieving version information failed, %d\n", 382 err); 383 goto done; 384 } 385 buf[sizeof(buf) - 1] = '\0'; 386 ptr = (char *)buf; 387 strsep(&ptr, "\n"); 388 389 /* Print fw version info */ 390 brcmf_info("Firmware: %s %s\n", ri->chipname, buf); 391 392 /* locate firmware version number for ethtool */ 393 ptr = strrchr(buf, ' '); 394 if (!ptr) { 395 bphy_err(drvr, "Retrieving version number failed"); 396 goto done; 397 } 398 strscpy(ifp->drvr->fwver, ptr + 1, sizeof(ifp->drvr->fwver)); 399 400 /* Query for 'clmver' to get CLM version info from firmware */ 401 memset(buf, 0, sizeof(buf)); 402 err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf)); 403 if (err) { 404 brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err); 405 } else { 406 buf[sizeof(buf) - 1] = '\0'; 407 clmver = (char *)buf; 408 409 /* Replace all newline/linefeed characters with space 410 * character 411 */ 412 strreplace(clmver, '\n', ' '); 413 414 /* store CLM version for adding it to revinfo debugfs file */ 415 memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver)); 416 417 brcmf_dbg(INFO, "CLM version = %s\n", clmver); 418 } 419 420 /* set mpc */ 421 err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); 422 if (err) { 423 bphy_err(drvr, "failed setting mpc\n"); 424 goto done; 425 } 426 427 brcmf_c_set_joinpref_default(ifp); 428 429 /* Setup event_msgs, enable E_IF */ 430 err = brcmf_fil_iovar_data_get(ifp, "event_msgs", fweh->event_mask, 431 fweh->event_mask_len); 432 if (err) { 433 bphy_err(drvr, "Get event_msgs error (%d)\n", err); 434 goto done; 435 } 436 /* 437 * BRCMF_E_IF can safely be used to set the appropriate bit 438 * in the event_mask as the firmware event code is guaranteed 439 * to match the value of BRCMF_E_IF because it is old cruft 440 * that all vendors have. 441 */ 442 setbit(fweh->event_mask, BRCMF_E_IF); 443 err = brcmf_fil_iovar_data_set(ifp, "event_msgs", fweh->event_mask, 444 fweh->event_mask_len); 445 if (err) { 446 bphy_err(drvr, "Set event_msgs error (%d)\n", err); 447 goto done; 448 } 449 450 /* Setup default scan channel time */ 451 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, 452 BRCMF_DEFAULT_SCAN_CHANNEL_TIME); 453 if (err) { 454 bphy_err(drvr, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", 455 err); 456 goto done; 457 } 458 459 /* Setup default scan unassoc time */ 460 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, 461 BRCMF_DEFAULT_SCAN_UNASSOC_TIME); 462 if (err) { 463 bphy_err(drvr, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", 464 err); 465 goto done; 466 } 467 468 /* Enable tx beamforming, errors can be ignored (not supported) */ 469 (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1); 470 done: 471 return err; 472 } 473 474 #ifndef CONFIG_BRCM_TRACING 475 void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...) 476 { 477 struct va_format vaf; 478 va_list args; 479 480 va_start(args, fmt); 481 482 vaf.fmt = fmt; 483 vaf.va = &args; 484 #if defined(__linux__) 485 if (bus) 486 dev_err(bus->dev, "%s: %pV", func, &vaf); 487 else 488 pr_err("%s: %pV", func, &vaf); 489 #elif defined(__FreeBSD__) 490 { 491 char *str; 492 vasprintf(&str, M_KMALLOC, vaf.fmt, args); 493 if (bus) 494 dev_err(bus->dev, "ERROR: %s: %s", func, str); 495 else 496 pr_err("ERROR: %s: %s", func, str); 497 free(str, M_KMALLOC); 498 } 499 #endif 500 501 va_end(args); 502 } 503 #endif 504 505 #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) 506 void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) 507 { 508 struct va_format vaf = { 509 .fmt = fmt, 510 }; 511 va_list args; 512 513 va_start(args, fmt); 514 vaf.va = &args; 515 if (brcmf_msg_level & level) 516 #if defined(__linux__) 517 pr_debug("%s %pV", func, &vaf); 518 #elif defined(__FreeBSD__) 519 { 520 char *str; 521 vasprintf(&str, M_KMALLOC, vaf.fmt, args); 522 pr_debug("%s %s", func, str); 523 free(str, M_KMALLOC); 524 } 525 #endif 526 trace_brcmf_dbg(level, func, &vaf); 527 va_end(args); 528 } 529 BRCMF_EXPORT_SYMBOL_GPL(__brcmf_dbg); 530 #endif 531 532 static void brcmf_mp_attach(void) 533 { 534 /* If module param firmware path is set then this will always be used, 535 * if not set then if available use the platform data version. To make 536 * sure it gets initialized at all, always copy the module param version 537 */ 538 strscpy(brcmf_mp_global.firmware_path, brcmf_firmware_path, 539 BRCMF_FW_ALTPATH_LEN); 540 if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) && 541 (brcmf_mp_global.firmware_path[0] == '\0')) { 542 strscpy(brcmf_mp_global.firmware_path, 543 brcmfmac_pdata->fw_alternative_path, 544 BRCMF_FW_ALTPATH_LEN); 545 } 546 } 547 548 struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, 549 enum brcmf_bus_type bus_type, 550 u32 chip, u32 chiprev) 551 { 552 struct brcmf_mp_device *settings; 553 struct brcmfmac_pd_device *device_pd; 554 bool found; 555 int i; 556 557 brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip, 558 chiprev); 559 settings = kzalloc(sizeof(*settings), GFP_ATOMIC); 560 if (!settings) 561 return NULL; 562 563 /* start by using the module parameters */ 564 settings->p2p_enable = !!brcmf_p2p_enable; 565 settings->feature_disable = brcmf_feature_disable; 566 settings->fcmode = brcmf_fcmode; 567 settings->roamoff = !!brcmf_roamoff; 568 settings->iapp = !!brcmf_iapp_enable; 569 #ifdef DEBUG 570 settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; 571 #endif 572 573 if (bus_type == BRCMF_BUSTYPE_SDIO) 574 settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz; 575 576 /* See if there is any device specific platform data configured */ 577 found = false; 578 if (brcmfmac_pdata) { 579 for (i = 0; i < brcmfmac_pdata->device_count; i++) { 580 device_pd = &brcmfmac_pdata->devices[i]; 581 if ((device_pd->bus_type == bus_type) && 582 (device_pd->id == chip) && 583 ((device_pd->rev == chiprev) || 584 (device_pd->rev == -1))) { 585 brcmf_dbg(INFO, "Platform data for device found\n"); 586 settings->country_codes = 587 device_pd->country_codes; 588 if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO) 589 memcpy(&settings->bus.sdio, 590 &device_pd->bus.sdio, 591 sizeof(settings->bus.sdio)); 592 found = true; 593 break; 594 } 595 } 596 } 597 if (!found) { 598 /* No platform data for this device, try OF and DMI data */ 599 brcmf_dmi_probe(settings, chip, chiprev); 600 if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER) { 601 kfree(settings); 602 return ERR_PTR(-EPROBE_DEFER); 603 } 604 brcmf_acpi_probe(dev, bus_type, settings); 605 } 606 return settings; 607 } 608 609 void brcmf_release_module_param(struct brcmf_mp_device *module_param) 610 { 611 kfree(module_param); 612 } 613 614 static int __init brcmf_common_pd_probe(struct platform_device *pdev) 615 { 616 brcmf_dbg(INFO, "Enter\n"); 617 618 brcmfmac_pdata = dev_get_platdata(&pdev->dev); 619 620 if (brcmfmac_pdata->power_on) 621 brcmfmac_pdata->power_on(); 622 623 return 0; 624 } 625 626 static void brcmf_common_pd_remove(struct platform_device *pdev) 627 { 628 brcmf_dbg(INFO, "Enter\n"); 629 630 if (brcmfmac_pdata->power_off) 631 brcmfmac_pdata->power_off(); 632 } 633 634 static struct platform_driver brcmf_pd = { 635 .remove = brcmf_common_pd_remove, 636 .driver = { 637 .name = BRCMFMAC_PDATA_NAME, 638 } 639 }; 640 641 static int __init brcmfmac_module_init(void) 642 { 643 int err; 644 645 /* Get the platform data (if available) for our devices */ 646 err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe); 647 if (err == -ENODEV) 648 brcmf_dbg(INFO, "No platform data available.\n"); 649 650 /* Initialize global module parameters */ 651 brcmf_mp_attach(); 652 653 /* Continue the initialization by registering the different busses */ 654 err = brcmf_core_init(); 655 if (err) { 656 if (brcmfmac_pdata) 657 platform_driver_unregister(&brcmf_pd); 658 } 659 660 return err; 661 } 662 663 static void __exit brcmfmac_module_exit(void) 664 { 665 brcmf_core_exit(); 666 if (brcmfmac_pdata) 667 platform_driver_unregister(&brcmf_pd); 668 } 669 670 module_init(brcmfmac_module_init); 671 module_exit(brcmfmac_module_exit); 672 673