return 0;
 }
 
-static int ath10k_core_fetch_board_file(struct ath10k *ar)
+static int ath10k_core_fetch_spec_board_file(struct ath10k *ar)
 {
-       int ret;
+       char filename[100];
+
+       scnprintf(filename, sizeof(filename), "board-%s-%s.bin",
+                 ath10k_bus_str(ar->hif.bus), ar->spec_board_id);
+
+       ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
+       if (IS_ERR(ar->board))
+               return PTR_ERR(ar->board);
+
+       ar->board_data = ar->board->data;
+       ar->board_len = ar->board->size;
+       ar->spec_board_loaded = true;
 
+       return 0;
+}
+
+static int ath10k_core_fetch_generic_board_file(struct ath10k *ar)
+{
        if (!ar->hw_params.fw.board) {
                ath10k_err(ar, "failed to find board file fw entry\n");
                return -EINVAL;
        ar->board = ath10k_fetch_fw_file(ar,
                                         ar->hw_params.fw.dir,
                                         ar->hw_params.fw.board);
-       if (IS_ERR(ar->board)) {
-               ret = PTR_ERR(ar->board);
-               ath10k_err(ar, "failed to fetch board data: %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(ar->board))
+               return PTR_ERR(ar->board);
 
        ar->board_data = ar->board->data;
        ar->board_len = ar->board->size;
+       ar->spec_board_loaded = false;
+
+       return 0;
+}
+
+static int ath10k_core_fetch_board_file(struct ath10k *ar)
+{
+       int ret;
+
+       if (strlen(ar->spec_board_id) > 0) {
+               ret = ath10k_core_fetch_spec_board_file(ar);
+               if (ret) {
+                       ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n",
+                                   ret);
+                       goto generic;
+               }
+
+               ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n",
+                          ar->spec_board_id);
+               return 0;
+       }
+
+generic:
+       ret = ath10k_core_fetch_generic_board_file(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to fetch generic board data: %d\n", ret);
+               return ret;
+       }
 
        return 0;
 }
 
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-       ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
+       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",
                    ar->hw_params.name,
                    ar->target_version,
                    ar->chip_id,
+                   (strlen(ar->spec_board_id) > 0 ? ", " : ""),
+                   ar->spec_board_id,
+                   (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded
+                    ? " fallback" : ""),
                    ar->hw->wiphy->fw_version,
                    ar->fw_api,
                    ar->htt.target_version_major,
 
        ar_pci->dev = &pdev->dev;
        ar_pci->ar = ar;
 
+       if (pdev->subsystem_vendor || pdev->subsystem_device)
+               scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id),
+                         "%04x:%04x:%04x:%04x",
+                         pdev->vendor, pdev->device,
+                         pdev->subsystem_vendor, pdev->subsystem_device);
+
        spin_lock_init(&ar_pci->ce_lock);
        setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
                    (unsigned long)ar);