aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-04-17 05:19:17 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2015-04-21 13:35:12 -0400
commitde57e2c8e1211cb7dea981f9f9818f1e1036a4d8 (patch)
tree5128f3b1ef0e4aca4aacde289ed66141b3c1fa44
parentd0ed74f38e778bc83d240e7b6aee146789fa0df8 (diff)
ath10k: allow loading device specific board files
Some devices differ slightly and require different board files. If wrong board data is used they crash or behave incorrectly. These devices can be differentiated by looking at PCI subsystem device id. That is the case for qca61x4 devices at least. The board specific filename is constructed as: board-<bus>-<id>.bin For PCI in particular it is: board-pci-<vendor>:<dev>:<subsys_vendor>:<subsys_dev>.bin These files are looked in device/hw specific directories. Hence for Killer 1525 (qca6174 hw2.1) ath10k will request: /lib/firmware/ath10k/QCA6174/hw2.1/board-pci-168c:003e:1a56:1525.bin To not break any existing setups (e.g. in case some devices in the wild already have subsys ids) if a board specific file isn't found a generic one is used which is the one which would be used until now. This guarantees that after upgrading a driver device will not suddenly stop working due to now-missing specific board file. If this is the case a "fallback" string is appended to the info string when driver boots. Keep in mind this is distinct from cal-pci-*.bin files which contain full calibration data and MAC address. Cal data is aimed at systems where calibration data is stored out of band, e.g. on nand flash instead of device EEPROM - an approach taken by some AP/router vendors. Board files are more of a template and needs some bits to be filled in by the OTP program using device EEPROM contents. One could argue to map subsystem ids to some board design codename strings instead of using raw ids when building the board filename. Using a mapping however would make it a lot more cumbersome and time consuming (due to how patches propagate over various kernel trees) to add support for some new device board designs. Adding a board file is a lot quicker and doesn't require recompilation. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c55
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c6
4 files changed, 62 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 70f5b7acc411..987b266278a8 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -482,10 +482,26 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
482 return 0; 482 return 0;
483} 483}
484 484
485static int ath10k_core_fetch_board_file(struct ath10k *ar) 485static int ath10k_core_fetch_spec_board_file(struct ath10k *ar)
486{ 486{
487 int ret; 487 char filename[100];
488
489 scnprintf(filename, sizeof(filename), "board-%s-%s.bin",
490 ath10k_bus_str(ar->hif.bus), ar->spec_board_id);
491
492 ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
493 if (IS_ERR(ar->board))
494 return PTR_ERR(ar->board);
495
496 ar->board_data = ar->board->data;
497 ar->board_len = ar->board->size;
498 ar->spec_board_loaded = true;
488 499
500 return 0;
501}
502
503static int ath10k_core_fetch_generic_board_file(struct ath10k *ar)
504{
489 if (!ar->hw_params.fw.board) { 505 if (!ar->hw_params.fw.board) {
490 ath10k_err(ar, "failed to find board file fw entry\n"); 506 ath10k_err(ar, "failed to find board file fw entry\n");
491 return -EINVAL; 507 return -EINVAL;
@@ -494,14 +510,39 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
494 ar->board = ath10k_fetch_fw_file(ar, 510 ar->board = ath10k_fetch_fw_file(ar,
495 ar->hw_params.fw.dir, 511 ar->hw_params.fw.dir,
496 ar->hw_params.fw.board); 512 ar->hw_params.fw.board);
497 if (IS_ERR(ar->board)) { 513 if (IS_ERR(ar->board))
498 ret = PTR_ERR(ar->board); 514 return PTR_ERR(ar->board);
499 ath10k_err(ar, "failed to fetch board data: %d\n", ret);
500 return ret;
501 }
502 515
503 ar->board_data = ar->board->data; 516 ar->board_data = ar->board->data;
504 ar->board_len = ar->board->size; 517 ar->board_len = ar->board->size;
518 ar->spec_board_loaded = false;
519
520 return 0;
521}
522
523static int ath10k_core_fetch_board_file(struct ath10k *ar)
524{
525 int ret;
526
527 if (strlen(ar->spec_board_id) > 0) {
528 ret = ath10k_core_fetch_spec_board_file(ar);
529 if (ret) {
530 ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n",
531 ret);
532 goto generic;
533 }
534
535 ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n",
536 ar->spec_board_id);
537 return 0;
538 }
539
540generic:
541 ret = ath10k_core_fetch_generic_board_file(ar);
542 if (ret) {
543 ath10k_err(ar, "failed to fetch generic board data: %d\n", ret);
544 return ret;
545 }
505 546
506 return 0; 547 return 0;
507} 548}
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index b0e8905ca325..7bb113a443d7 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -592,6 +592,9 @@ struct ath10k {
592 592
593 const struct firmware *cal_file; 593 const struct firmware *cal_file;
594 594
595 char spec_board_id[100];
596 bool spec_board_loaded;
597
595 int fw_api; 598 int fw_api;
596 enum ath10k_cal_mode cal_mode; 599 enum ath10k_cal_mode cal_mode;
597 600
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1391f00f2b8f..8fa606a9c4dd 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -124,10 +124,14 @@ EXPORT_SYMBOL(ath10k_info);
124 124
125void ath10k_print_driver_info(struct ath10k *ar) 125void ath10k_print_driver_info(struct ath10k *ar)
126{ 126{
127 ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n", 127 ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
128 ar->hw_params.name, 128 ar->hw_params.name,
129 ar->target_version, 129 ar->target_version,
130 ar->chip_id, 130 ar->chip_id,
131 (strlen(ar->spec_board_id) > 0 ? ", " : ""),
132 ar->spec_board_id,
133 (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded
134 ? " fallback" : ""),
131 ar->hw->wiphy->fw_version, 135 ar->hw->wiphy->fw_version,
132 ar->fw_api, 136 ar->fw_api,
133 ar->htt.target_version_major, 137 ar->htt.target_version_major,
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 1f770ac28df4..9dc0079a8ea6 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2627,6 +2627,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
2627 ar_pci->dev = &pdev->dev; 2627 ar_pci->dev = &pdev->dev;
2628 ar_pci->ar = ar; 2628 ar_pci->ar = ar;
2629 2629
2630 if (pdev->subsystem_vendor || pdev->subsystem_device)
2631 scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id),
2632 "%04x:%04x:%04x:%04x",
2633 pdev->vendor, pdev->device,
2634 pdev->subsystem_vendor, pdev->subsystem_device);
2635
2630 spin_lock_init(&ar_pci->ce_lock); 2636 spin_lock_init(&ar_pci->ce_lock);
2631 setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 2637 setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
2632 (unsigned long)ar); 2638 (unsigned long)ar);