| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Bluetooth support for Broadcom devices |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright (C) 2015 Intel Corporation |
|---|
| 6 | | - * |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License |
|---|
| 19 | | - * along with this program; if not, write to the Free Software |
|---|
| 20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 21 | | - * |
|---|
| 22 | 7 | */ |
|---|
| 23 | 8 | |
|---|
| 9 | +#ifndef __GENKSYMS__ // ANDROID CRC kabi preservation hack due to commit 76dd7893bd10 |
|---|
| 10 | +#include <linux/efi.h> |
|---|
| 11 | +#endif |
|---|
| 24 | 12 | #include <linux/module.h> |
|---|
| 25 | 13 | #include <linux/firmware.h> |
|---|
| 26 | 14 | #include <asm/unaligned.h> |
|---|
| .. | .. |
|---|
| 33 | 21 | #define VERSION "0.1" |
|---|
| 34 | 22 | |
|---|
| 35 | 23 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) |
|---|
| 24 | +#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}}) |
|---|
| 25 | +#define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}}) |
|---|
| 26 | +#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) |
|---|
| 36 | 27 | #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) |
|---|
| 37 | 28 | #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) |
|---|
| 29 | +#define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}}) |
|---|
| 30 | +#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}}) |
|---|
| 31 | +#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) |
|---|
| 32 | + |
|---|
| 33 | +#define BCM_FW_NAME_LEN 64 |
|---|
| 34 | +#define BCM_FW_NAME_COUNT_MAX 2 |
|---|
| 35 | +/* For kmalloc-ing the fw-name array instead of putting it on the stack */ |
|---|
| 36 | +typedef char bcm_fw_name[BCM_FW_NAME_LEN]; |
|---|
| 37 | + |
|---|
| 38 | +#ifdef CONFIG_EFI |
|---|
| 39 | +static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev) |
|---|
| 40 | +{ |
|---|
| 41 | + efi_guid_t guid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61, 0xb5, 0x1f, |
|---|
| 42 | + 0x43, 0x26, 0x81, 0x23, 0xd1, 0x13); |
|---|
| 43 | + bdaddr_t efi_bdaddr, bdaddr; |
|---|
| 44 | + efi_status_t status; |
|---|
| 45 | + unsigned long len; |
|---|
| 46 | + int ret; |
|---|
| 47 | + |
|---|
| 48 | + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) |
|---|
| 49 | + return -EOPNOTSUPP; |
|---|
| 50 | + |
|---|
| 51 | + len = sizeof(efi_bdaddr); |
|---|
| 52 | + status = efi.get_variable(L"BDADDR", &guid, NULL, &len, &efi_bdaddr); |
|---|
| 53 | + if (status != EFI_SUCCESS) |
|---|
| 54 | + return -ENXIO; |
|---|
| 55 | + |
|---|
| 56 | + if (len != sizeof(efi_bdaddr)) |
|---|
| 57 | + return -EIO; |
|---|
| 58 | + |
|---|
| 59 | + baswap(&bdaddr, &efi_bdaddr); |
|---|
| 60 | + |
|---|
| 61 | + ret = btbcm_set_bdaddr(hdev, &bdaddr); |
|---|
| 62 | + if (ret) |
|---|
| 63 | + return ret; |
|---|
| 64 | + |
|---|
| 65 | + bt_dev_info(hdev, "BCM: Using EFI device address (%pMR)", &bdaddr); |
|---|
| 66 | + return 0; |
|---|
| 67 | +} |
|---|
| 68 | +#else |
|---|
| 69 | +static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev) |
|---|
| 70 | +{ |
|---|
| 71 | + return -EOPNOTSUPP; |
|---|
| 72 | +} |
|---|
| 73 | +#endif |
|---|
| 38 | 74 | |
|---|
| 39 | 75 | int btbcm_check_bdaddr(struct hci_dev *hdev) |
|---|
| 40 | 76 | { |
|---|
| .. | .. |
|---|
| 45 | 81 | HCI_INIT_TIMEOUT); |
|---|
| 46 | 82 | if (IS_ERR(skb)) { |
|---|
| 47 | 83 | int err = PTR_ERR(skb); |
|---|
| 84 | + |
|---|
| 48 | 85 | bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err); |
|---|
| 49 | 86 | return err; |
|---|
| 50 | 87 | } |
|---|
| .. | .. |
|---|
| 64 | 101 | * The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller |
|---|
| 65 | 102 | * with no configured address. |
|---|
| 66 | 103 | * |
|---|
| 104 | + * The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller |
|---|
| 105 | + * with no configured address. |
|---|
| 106 | + * |
|---|
| 107 | + * The address 20:76:A0:00:56:79 indicates a BCM2076B1 controller |
|---|
| 108 | + * with no configured address. |
|---|
| 109 | + * |
|---|
| 67 | 110 | * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller |
|---|
| 68 | 111 | * with waiting for configuration state. |
|---|
| 69 | 112 | * |
|---|
| 70 | 113 | * The address 43:30:B1:00:00:00 indicates a BCM4330B1 controller |
|---|
| 71 | 114 | * with waiting for configuration state. |
|---|
| 115 | + * |
|---|
| 116 | + * The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller |
|---|
| 117 | + * with no configured address. |
|---|
| 72 | 118 | */ |
|---|
| 73 | 119 | if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || |
|---|
| 120 | + !bacmp(&bda->bdaddr, BDADDR_BCM20702A1) || |
|---|
| 121 | + !bacmp(&bda->bdaddr, BDADDR_BCM2076B1) || |
|---|
| 74 | 122 | !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || |
|---|
| 75 | | - !bacmp(&bda->bdaddr, BDADDR_BCM4330B1)) { |
|---|
| 76 | | - bt_dev_info(hdev, "BCM: Using default device address (%pMR)", |
|---|
| 77 | | - &bda->bdaddr); |
|---|
| 78 | | - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); |
|---|
| 123 | + !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) || |
|---|
| 124 | + !bacmp(&bda->bdaddr, BDADDR_BCM4334B0) || |
|---|
| 125 | + !bacmp(&bda->bdaddr, BDADDR_BCM4345C5) || |
|---|
| 126 | + !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) || |
|---|
| 127 | + !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) { |
|---|
| 128 | + /* Try falling back to BDADDR EFI variable */ |
|---|
| 129 | + if (btbcm_set_bdaddr_from_efi(hdev) != 0) { |
|---|
| 130 | + bt_dev_info(hdev, "BCM: Using default device address (%pMR)", |
|---|
| 131 | + &bda->bdaddr); |
|---|
| 132 | + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); |
|---|
| 133 | + } |
|---|
| 79 | 134 | } |
|---|
| 80 | 135 | |
|---|
| 81 | 136 | kfree_skb(skb); |
|---|
| .. | .. |
|---|
| 100 | 155 | return 0; |
|---|
| 101 | 156 | } |
|---|
| 102 | 157 | EXPORT_SYMBOL_GPL(btbcm_set_bdaddr); |
|---|
| 158 | + |
|---|
| 159 | +int btbcm_read_pcm_int_params(struct hci_dev *hdev, |
|---|
| 160 | + struct bcm_set_pcm_int_params *params) |
|---|
| 161 | +{ |
|---|
| 162 | + struct sk_buff *skb; |
|---|
| 163 | + int err = 0; |
|---|
| 164 | + |
|---|
| 165 | + skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT); |
|---|
| 166 | + if (IS_ERR(skb)) { |
|---|
| 167 | + err = PTR_ERR(skb); |
|---|
| 168 | + bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err); |
|---|
| 169 | + return err; |
|---|
| 170 | + } |
|---|
| 171 | + |
|---|
| 172 | + if (skb->len != 6 || skb->data[0]) { |
|---|
| 173 | + bt_dev_err(hdev, "BCM: Read PCM int params length mismatch"); |
|---|
| 174 | + kfree_skb(skb); |
|---|
| 175 | + return -EIO; |
|---|
| 176 | + } |
|---|
| 177 | + |
|---|
| 178 | + if (params) |
|---|
| 179 | + memcpy(params, skb->data + 1, 5); |
|---|
| 180 | + |
|---|
| 181 | + kfree_skb(skb); |
|---|
| 182 | + |
|---|
| 183 | + return 0; |
|---|
| 184 | +} |
|---|
| 185 | +EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params); |
|---|
| 186 | + |
|---|
| 187 | +int btbcm_write_pcm_int_params(struct hci_dev *hdev, |
|---|
| 188 | + const struct bcm_set_pcm_int_params *params) |
|---|
| 189 | +{ |
|---|
| 190 | + struct sk_buff *skb; |
|---|
| 191 | + int err; |
|---|
| 192 | + |
|---|
| 193 | + skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT); |
|---|
| 194 | + if (IS_ERR(skb)) { |
|---|
| 195 | + err = PTR_ERR(skb); |
|---|
| 196 | + bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err); |
|---|
| 197 | + return err; |
|---|
| 198 | + } |
|---|
| 199 | + kfree_skb(skb); |
|---|
| 200 | + |
|---|
| 201 | + return 0; |
|---|
| 202 | +} |
|---|
| 203 | +EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params); |
|---|
| 103 | 204 | |
|---|
| 104 | 205 | int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) |
|---|
| 105 | 206 | { |
|---|
| .. | .. |
|---|
| 171 | 272 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); |
|---|
| 172 | 273 | if (IS_ERR(skb)) { |
|---|
| 173 | 274 | int err = PTR_ERR(skb); |
|---|
| 275 | + |
|---|
| 174 | 276 | bt_dev_err(hdev, "BCM: Reset failed (%d)", err); |
|---|
| 175 | 277 | return err; |
|---|
| 176 | 278 | } |
|---|
| .. | .. |
|---|
| 304 | 406 | bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]); |
|---|
| 305 | 407 | kfree_skb(skb); |
|---|
| 306 | 408 | |
|---|
| 409 | + return 0; |
|---|
| 410 | +} |
|---|
| 411 | + |
|---|
| 412 | +static int btbcm_print_local_name(struct hci_dev *hdev) |
|---|
| 413 | +{ |
|---|
| 414 | + struct sk_buff *skb; |
|---|
| 415 | + |
|---|
| 307 | 416 | /* Read Local Name */ |
|---|
| 308 | 417 | skb = btbcm_read_local_name(hdev); |
|---|
| 309 | 418 | if (IS_ERR(skb)) |
|---|
| .. | .. |
|---|
| 322 | 431 | |
|---|
| 323 | 432 | static const struct bcm_subver_table bcm_uart_subver_table[] = { |
|---|
| 324 | 433 | { 0x4103, "BCM4330B1" }, /* 002.001.003 */ |
|---|
| 434 | + { 0x410d, "BCM4334B0" }, /* 002.001.013 */ |
|---|
| 325 | 435 | { 0x410e, "BCM43341B0" }, /* 002.001.014 */ |
|---|
| 436 | + { 0x4204, "BCM2076B1" }, /* 002.002.004 */ |
|---|
| 326 | 437 | { 0x4406, "BCM4324B3" }, /* 002.004.006 */ |
|---|
| 327 | 438 | { 0x4606, "BCM4324B5" }, /* 002.006.006 */ |
|---|
| 328 | 439 | { 0x6109, "BCM4335C0" }, /* 003.001.009 */ |
|---|
| .. | .. |
|---|
| 330 | 441 | { 0x2122, "BCM4343A0" }, /* 001.001.034 */ |
|---|
| 331 | 442 | { 0x2209, "BCM43430A1" }, /* 001.002.009 */ |
|---|
| 332 | 443 | { 0x6119, "BCM4345C0" }, /* 003.001.025 */ |
|---|
| 444 | + { 0x6606, "BCM4345C5" }, /* 003.006.006 */ |
|---|
| 333 | 445 | { 0x230f, "BCM4356A2" }, /* 001.003.015 */ |
|---|
| 446 | + { 0x220e, "BCM20702A1" }, /* 001.002.014 */ |
|---|
| 447 | + { 0x420d, "BCM4349B1" }, /* 002.002.013 */ |
|---|
| 448 | + { 0x420e, "BCM4349B1" }, /* 002.002.014 */ |
|---|
| 449 | + { 0x4217, "BCM4329B1" }, /* 002.002.023 */ |
|---|
| 450 | + { 0x6106, "BCM4359C0" }, /* 003.001.006 */ |
|---|
| 451 | + { 0x4106, "BCM4335A0" }, /* 002.001.006 */ |
|---|
| 334 | 452 | { } |
|---|
| 335 | 453 | }; |
|---|
| 336 | 454 | |
|---|
| .. | .. |
|---|
| 341 | 459 | { 0x2118, "BCM20702A0" }, /* 001.001.024 */ |
|---|
| 342 | 460 | { 0x2126, "BCM4335A0" }, /* 001.001.038 */ |
|---|
| 343 | 461 | { 0x220e, "BCM20702A1" }, /* 001.002.014 */ |
|---|
| 344 | | - { 0x230f, "BCM4354A2" }, /* 001.003.015 */ |
|---|
| 462 | + { 0x230f, "BCM4356A2" }, /* 001.003.015 */ |
|---|
| 345 | 463 | { 0x4106, "BCM4335B0" }, /* 002.001.006 */ |
|---|
| 346 | 464 | { 0x410e, "BCM20702B0" }, /* 002.001.014 */ |
|---|
| 347 | 465 | { 0x6109, "BCM4335C0" }, /* 003.001.009 */ |
|---|
| 348 | 466 | { 0x610c, "BCM4354" }, /* 003.001.012 */ |
|---|
| 467 | + { 0x6607, "BCM4350C5" }, /* 003.006.007 */ |
|---|
| 349 | 468 | { } |
|---|
| 350 | 469 | }; |
|---|
| 351 | 470 | |
|---|
| 352 | | -int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, |
|---|
| 353 | | - bool reinit) |
|---|
| 471 | +int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) |
|---|
| 354 | 472 | { |
|---|
| 355 | 473 | u16 subver, rev, pid, vid; |
|---|
| 356 | | - const char *hw_name = "BCM"; |
|---|
| 357 | 474 | struct sk_buff *skb; |
|---|
| 358 | 475 | struct hci_rp_read_local_version *ver; |
|---|
| 359 | 476 | const struct bcm_subver_table *bcm_subver_table; |
|---|
| 477 | + const char *hw_name = NULL; |
|---|
| 478 | + char postfix[16] = ""; |
|---|
| 479 | + int fw_name_count = 0; |
|---|
| 480 | + bcm_fw_name *fw_name; |
|---|
| 481 | + const struct firmware *fw; |
|---|
| 360 | 482 | int i, err; |
|---|
| 361 | 483 | |
|---|
| 362 | 484 | /* Reset */ |
|---|
| .. | .. |
|---|
| 375 | 497 | kfree_skb(skb); |
|---|
| 376 | 498 | |
|---|
| 377 | 499 | /* Read controller information */ |
|---|
| 378 | | - if (!reinit) { |
|---|
| 500 | + if (!(*fw_load_done)) { |
|---|
| 379 | 501 | err = btbcm_read_info(hdev); |
|---|
| 380 | 502 | if (err) |
|---|
| 381 | 503 | return err; |
|---|
| 382 | 504 | } |
|---|
| 383 | | - |
|---|
| 384 | | - /* Upper nibble of rev should be between 0 and 3? */ |
|---|
| 385 | | - if (((rev & 0xf000) >> 12) > 3) |
|---|
| 386 | | - return 0; |
|---|
| 505 | + err = btbcm_print_local_name(hdev); |
|---|
| 506 | + if (err) |
|---|
| 507 | + return err; |
|---|
| 387 | 508 | |
|---|
| 388 | 509 | bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : |
|---|
| 389 | 510 | bcm_uart_subver_table; |
|---|
| .. | .. |
|---|
| 395 | 516 | } |
|---|
| 396 | 517 | } |
|---|
| 397 | 518 | |
|---|
| 519 | + bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", |
|---|
| 520 | + hw_name ? hw_name : "BCM", (subver & 0xe000) >> 13, |
|---|
| 521 | + (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); |
|---|
| 522 | + |
|---|
| 523 | + if (*fw_load_done) |
|---|
| 524 | + return 0; |
|---|
| 525 | + |
|---|
| 398 | 526 | if (hdev->bus == HCI_USB) { |
|---|
| 399 | 527 | /* Read USB Product Info */ |
|---|
| 400 | 528 | skb = btbcm_read_usb_product(hdev); |
|---|
| .. | .. |
|---|
| 405 | 533 | pid = get_unaligned_le16(skb->data + 3); |
|---|
| 406 | 534 | kfree_skb(skb); |
|---|
| 407 | 535 | |
|---|
| 408 | | - snprintf(fw_name, len, "brcm/%s-%4.4x-%4.4x.hcd", |
|---|
| 409 | | - hw_name, vid, pid); |
|---|
| 410 | | - } else { |
|---|
| 411 | | - snprintf(fw_name, len, "brcm/%s.hcd", hw_name); |
|---|
| 536 | + snprintf(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid); |
|---|
| 412 | 537 | } |
|---|
| 413 | 538 | |
|---|
| 414 | | - bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", |
|---|
| 415 | | - hw_name, (subver & 0xe000) >> 13, |
|---|
| 416 | | - (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); |
|---|
| 539 | + fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL); |
|---|
| 540 | + if (!fw_name) |
|---|
| 541 | + return -ENOMEM; |
|---|
| 417 | 542 | |
|---|
| 543 | + if (hw_name) { |
|---|
| 544 | + snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN, |
|---|
| 545 | + "brcm/%s%s.hcd", hw_name, postfix); |
|---|
| 546 | + fw_name_count++; |
|---|
| 547 | + } |
|---|
| 548 | + |
|---|
| 549 | + snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN, |
|---|
| 550 | + "brcm/BCM%s.hcd", postfix); |
|---|
| 551 | + fw_name_count++; |
|---|
| 552 | + |
|---|
| 553 | + for (i = 0; i < fw_name_count; i++) { |
|---|
| 554 | + err = firmware_request_nowarn(&fw, fw_name[i], &hdev->dev); |
|---|
| 555 | + if (err == 0) { |
|---|
| 556 | + bt_dev_info(hdev, "%s '%s' Patch", |
|---|
| 557 | + hw_name ? hw_name : "BCM", fw_name[i]); |
|---|
| 558 | + *fw_load_done = true; |
|---|
| 559 | + break; |
|---|
| 560 | + } |
|---|
| 561 | + } |
|---|
| 562 | + |
|---|
| 563 | + if (*fw_load_done) { |
|---|
| 564 | + err = btbcm_patchram(hdev, fw); |
|---|
| 565 | + if (err) |
|---|
| 566 | + bt_dev_info(hdev, "BCM: Patch failed (%d)", err); |
|---|
| 567 | + |
|---|
| 568 | + release_firmware(fw); |
|---|
| 569 | + } else { |
|---|
| 570 | + bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:"); |
|---|
| 571 | + for (i = 0; i < fw_name_count; i++) |
|---|
| 572 | + bt_dev_err(hdev, "BCM: '%s'", fw_name[i]); |
|---|
| 573 | + } |
|---|
| 574 | + |
|---|
| 575 | + kfree(fw_name); |
|---|
| 418 | 576 | return 0; |
|---|
| 419 | 577 | } |
|---|
| 420 | 578 | EXPORT_SYMBOL_GPL(btbcm_initialize); |
|---|
| 421 | 579 | |
|---|
| 422 | | -int btbcm_finalize(struct hci_dev *hdev) |
|---|
| 580 | +int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) |
|---|
| 423 | 581 | { |
|---|
| 424 | | - char fw_name[64]; |
|---|
| 425 | 582 | int err; |
|---|
| 426 | 583 | |
|---|
| 427 | | - /* Re-initialize */ |
|---|
| 428 | | - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); |
|---|
| 429 | | - if (err) |
|---|
| 430 | | - return err; |
|---|
| 584 | + /* Re-initialize if necessary */ |
|---|
| 585 | + if (*fw_load_done) { |
|---|
| 586 | + err = btbcm_initialize(hdev, fw_load_done); |
|---|
| 587 | + if (err) |
|---|
| 588 | + return err; |
|---|
| 589 | + } |
|---|
| 431 | 590 | |
|---|
| 432 | 591 | btbcm_check_bdaddr(hdev); |
|---|
| 433 | 592 | |
|---|
| .. | .. |
|---|
| 439 | 598 | |
|---|
| 440 | 599 | int btbcm_setup_patchram(struct hci_dev *hdev) |
|---|
| 441 | 600 | { |
|---|
| 442 | | - char fw_name[64]; |
|---|
| 443 | | - const struct firmware *fw; |
|---|
| 444 | | - struct sk_buff *skb; |
|---|
| 601 | + bool fw_load_done = false; |
|---|
| 445 | 602 | int err; |
|---|
| 446 | 603 | |
|---|
| 447 | 604 | /* Initialize */ |
|---|
| 448 | | - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), false); |
|---|
| 605 | + err = btbcm_initialize(hdev, &fw_load_done); |
|---|
| 449 | 606 | if (err) |
|---|
| 450 | 607 | return err; |
|---|
| 451 | 608 | |
|---|
| 452 | | - err = request_firmware(&fw, fw_name, &hdev->dev); |
|---|
| 453 | | - if (err < 0) { |
|---|
| 454 | | - bt_dev_info(hdev, "BCM: Patch %s not found", fw_name); |
|---|
| 455 | | - goto done; |
|---|
| 456 | | - } |
|---|
| 457 | | - |
|---|
| 458 | | - btbcm_patchram(hdev, fw); |
|---|
| 459 | | - |
|---|
| 460 | | - release_firmware(fw); |
|---|
| 461 | | - |
|---|
| 462 | | - /* Re-initialize */ |
|---|
| 463 | | - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); |
|---|
| 464 | | - if (err) |
|---|
| 465 | | - return err; |
|---|
| 466 | | - |
|---|
| 467 | | - /* Read Local Name */ |
|---|
| 468 | | - skb = btbcm_read_local_name(hdev); |
|---|
| 469 | | - if (IS_ERR(skb)) |
|---|
| 470 | | - return PTR_ERR(skb); |
|---|
| 471 | | - |
|---|
| 472 | | - bt_dev_info(hdev, "%s", (char *)(skb->data + 1)); |
|---|
| 473 | | - kfree_skb(skb); |
|---|
| 474 | | - |
|---|
| 475 | | -done: |
|---|
| 476 | | - btbcm_check_bdaddr(hdev); |
|---|
| 477 | | - |
|---|
| 478 | | - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); |
|---|
| 479 | | - |
|---|
| 480 | | - return 0; |
|---|
| 609 | + /* Re-initialize after loading Patch */ |
|---|
| 610 | + return btbcm_finalize(hdev, &fw_load_done); |
|---|
| 481 | 611 | } |
|---|
| 482 | 612 | EXPORT_SYMBOL_GPL(btbcm_setup_patchram); |
|---|
| 483 | 613 | |
|---|