Loading drivers/net/wireless/ath/wil6210/fw.h +8 −3 Original line number Diff line number Diff line /* * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading Loading @@ -109,12 +109,17 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ /* brd file info encoded inside a comment record */ #define WIL_BRD_FILE_MAGIC (0xabcddcbb) struct brd_info { __le32 base_addr; __le32 max_size_bytes; } __packed; struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ /* identifies brd file record */ struct wil_fw_record_comment_hdr hdr; __le32 version; __le32 base_addr; __le32 max_size_bytes; struct brd_info brd_info[0]; } __packed; /* perform action Loading drivers/net/wireless/ath/wil6210/fw_inc.c +109 −39 Original line number Diff line number Diff line Loading @@ -156,17 +156,52 @@ fw_handle_brd_file(struct wil6210_priv *wil, const void *data, size_t size) { const struct wil_fw_record_brd_file *rec = data; u32 max_num_ent, i, ent_size; if (size < sizeof(*rec)) { wil_err_fw(wil, "brd_file record too short: %zu\n", size); return 0; if (size <= offsetof(struct wil_fw_record_brd_file, brd_info)) { wil_err(wil, "board record too short, size %zu\n", size); return -EINVAL; } ent_size = size - offsetof(struct wil_fw_record_brd_file, brd_info); max_num_ent = ent_size / sizeof(struct brd_info); if (!max_num_ent) { wil_err(wil, "brd info entries are missing\n"); return -EINVAL; } wil->brd_info = kcalloc(max_num_ent, sizeof(struct wil_brd_info), GFP_KERNEL); if (!wil->brd_info) return -ENOMEM; for (i = 0; i < max_num_ent; i++) { wil->brd_info[i].file_addr = le32_to_cpu(rec->brd_info[i].base_addr); wil->brd_info[i].file_max_size = le32_to_cpu(rec->brd_info[i].max_size_bytes); if (!wil->brd_info[i].file_addr) break; wil_dbg_fw(wil, "brd info %d: file_addr 0x%x, file_max_size %d\n", i, wil->brd_info[i].file_addr, wil->brd_info[i].file_max_size); } wil->brd_file_addr = le32_to_cpu(rec->base_addr); wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes); wil->num_of_brd_entries = i; if (wil->num_of_brd_entries == 0) { kfree(wil->brd_info); wil->brd_info = NULL; wil_dbg_fw(wil, "no valid brd info entries, using brd file addr\n"); wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n", wil->brd_file_addr, wil->brd_file_max_size); } else { wil_dbg_fw(wil, "num of brd info entries %d\n", wil->num_of_brd_entries); } return 0; } Loading Loading @@ -634,6 +669,11 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name, } wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, fw->size); /* re-initialize board info params */ wil->num_of_brd_entries = 0; kfree(wil->brd_info); wil->brd_info = NULL; for (sz = fw->size, d = fw->data; sz; sz -= rc1, d += rc1) { rc1 = wil_fw_verify(wil, d, sz); if (rc1 < 0) { Loading Loading @@ -662,11 +702,13 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, { int rc = 0; const struct wil_fw_record_head *hdr = data; size_t s, hdr_sz; size_t s, hdr_sz = 0; u16 type; int i = 0; /* Assuming the board file includes only one header record and one data * record. Each record starts with wil_fw_record_head. /* Assuming the board file includes only one file header * and one or several data records. * Each record starts with wil_fw_record_head. */ if (size < sizeof(*hdr)) return -EINVAL; Loading @@ -674,14 +716,24 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, if (s > size) return -EINVAL; /* Skip the header record and handle the data record */ hdr = (const void *)hdr + s; /* Skip the header record and handle the data records */ size -= s; for (hdr = data + s;; hdr = (const void *)hdr + s, size -= s, i++) { if (size < sizeof(*hdr)) return -EINVAL; hdr_sz = le32_to_cpu(hdr->size); break; if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size) if (i >= wil->num_of_brd_entries) { wil_err_fw(wil, "Too many brd records: %d, num of expected entries %d\n", i, wil->num_of_brd_entries); break; } hdr_sz = le32_to_cpu(hdr->size); s = sizeof(*hdr) + hdr_sz; if (wil->brd_info[i].file_max_size && hdr_sz > wil->brd_info[i].file_max_size) return -EINVAL; if (sizeof(*hdr) + hdr_sz > size) return -EINVAL; Loading @@ -692,7 +744,8 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, } type = le16_to_cpu(hdr->type); if (type != wil_fw_type_data) { wil_err_fw(wil, "invalid record type for board file: %d\n", wil_err_fw(wil, "invalid record type for board file: %d\n", type); return -EINVAL; } Loading @@ -701,15 +754,31 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, return -EINVAL; } wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n", wil->brd_file_addr); wil_dbg_fw(wil, "using info from fw file for record %d: addr[0x%08x], max size %d\n", i, wil->brd_info[i].file_addr, wil->brd_info[i].file_max_size); rc = __fw_handle_data(wil, &hdr[1], hdr_sz, cpu_to_le32(wil->brd_file_addr)); cpu_to_le32(wil->brd_info[i].file_addr)); if (rc) return rc; } if (size) { wil_err_fw(wil, "unprocessed bytes: %zu\n", size); if (size >= sizeof(*hdr)) { wil_err_fw(wil, "Stop at offset %ld record type %d [%zd bytes]\n", (long)((const void *)hdr - data), le16_to_cpu(hdr->type), hdr_sz); } return -EINVAL; } return 0; } /** * wil_request_board - Request board file * Loading Loading @@ -738,7 +807,8 @@ int wil_request_board(struct wil6210_priv *wil, const char *name) rc = dlen; goto out; } /* Process the data record */ /* Process the data records */ rc = wil_brd_process(wil, brd->data, dlen); out: Loading drivers/net/wireless/ath/wil6210/main.c +2 −1 Original line number Diff line number Diff line Loading @@ -860,6 +860,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) destroy_workqueue(wil->wq_service); destroy_workqueue(wil->wmi_wq); kfree(wil->board_file); kfree(wil->brd_info); } static void wil_shutdown_bl(struct wil6210_priv *wil) Loading Loading @@ -1760,7 +1761,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil_request_firmware(wil, wil->wil_fw_name, true); if (rc) goto out; if (wil->brd_file_addr) if (wil->num_of_brd_entries) rc = wil_request_board(wil, board_file); else rc = wil_request_firmware(wil, board_file, true); Loading drivers/net/wireless/ath/wil6210/pcie_bus.c +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ int wil_set_capabilities(struct wil6210_priv *wil) min(sizeof(wil->platform_capa), sizeof(platform_capa))); } wil_info(wil, "platform_capa 0x%lx\n", *wil->platform_capa); /* extract FW capabilities from file without loading the FW */ wil_request_firmware(wil, wil->wil_fw_name, false); wil_refresh_fw_capabilities(wil); Loading drivers/net/wireless/ath/wil6210/txrx.c +3 −0 Original line number Diff line number Diff line Loading @@ -1782,6 +1782,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, } } if (!_desc) goto mem_error; /* first descriptor may also be the last. * in this case d pointer is invalid */ Loading Loading
drivers/net/wireless/ath/wil6210/fw.h +8 −3 Original line number Diff line number Diff line /* * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading Loading @@ -109,12 +109,17 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ /* brd file info encoded inside a comment record */ #define WIL_BRD_FILE_MAGIC (0xabcddcbb) struct brd_info { __le32 base_addr; __le32 max_size_bytes; } __packed; struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ /* identifies brd file record */ struct wil_fw_record_comment_hdr hdr; __le32 version; __le32 base_addr; __le32 max_size_bytes; struct brd_info brd_info[0]; } __packed; /* perform action Loading
drivers/net/wireless/ath/wil6210/fw_inc.c +109 −39 Original line number Diff line number Diff line Loading @@ -156,17 +156,52 @@ fw_handle_brd_file(struct wil6210_priv *wil, const void *data, size_t size) { const struct wil_fw_record_brd_file *rec = data; u32 max_num_ent, i, ent_size; if (size < sizeof(*rec)) { wil_err_fw(wil, "brd_file record too short: %zu\n", size); return 0; if (size <= offsetof(struct wil_fw_record_brd_file, brd_info)) { wil_err(wil, "board record too short, size %zu\n", size); return -EINVAL; } ent_size = size - offsetof(struct wil_fw_record_brd_file, brd_info); max_num_ent = ent_size / sizeof(struct brd_info); if (!max_num_ent) { wil_err(wil, "brd info entries are missing\n"); return -EINVAL; } wil->brd_info = kcalloc(max_num_ent, sizeof(struct wil_brd_info), GFP_KERNEL); if (!wil->brd_info) return -ENOMEM; for (i = 0; i < max_num_ent; i++) { wil->brd_info[i].file_addr = le32_to_cpu(rec->brd_info[i].base_addr); wil->brd_info[i].file_max_size = le32_to_cpu(rec->brd_info[i].max_size_bytes); if (!wil->brd_info[i].file_addr) break; wil_dbg_fw(wil, "brd info %d: file_addr 0x%x, file_max_size %d\n", i, wil->brd_info[i].file_addr, wil->brd_info[i].file_max_size); } wil->brd_file_addr = le32_to_cpu(rec->base_addr); wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes); wil->num_of_brd_entries = i; if (wil->num_of_brd_entries == 0) { kfree(wil->brd_info); wil->brd_info = NULL; wil_dbg_fw(wil, "no valid brd info entries, using brd file addr\n"); wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n", wil->brd_file_addr, wil->brd_file_max_size); } else { wil_dbg_fw(wil, "num of brd info entries %d\n", wil->num_of_brd_entries); } return 0; } Loading Loading @@ -634,6 +669,11 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name, } wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, fw->size); /* re-initialize board info params */ wil->num_of_brd_entries = 0; kfree(wil->brd_info); wil->brd_info = NULL; for (sz = fw->size, d = fw->data; sz; sz -= rc1, d += rc1) { rc1 = wil_fw_verify(wil, d, sz); if (rc1 < 0) { Loading Loading @@ -662,11 +702,13 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, { int rc = 0; const struct wil_fw_record_head *hdr = data; size_t s, hdr_sz; size_t s, hdr_sz = 0; u16 type; int i = 0; /* Assuming the board file includes only one header record and one data * record. Each record starts with wil_fw_record_head. /* Assuming the board file includes only one file header * and one or several data records. * Each record starts with wil_fw_record_head. */ if (size < sizeof(*hdr)) return -EINVAL; Loading @@ -674,14 +716,24 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, if (s > size) return -EINVAL; /* Skip the header record and handle the data record */ hdr = (const void *)hdr + s; /* Skip the header record and handle the data records */ size -= s; for (hdr = data + s;; hdr = (const void *)hdr + s, size -= s, i++) { if (size < sizeof(*hdr)) return -EINVAL; hdr_sz = le32_to_cpu(hdr->size); break; if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size) if (i >= wil->num_of_brd_entries) { wil_err_fw(wil, "Too many brd records: %d, num of expected entries %d\n", i, wil->num_of_brd_entries); break; } hdr_sz = le32_to_cpu(hdr->size); s = sizeof(*hdr) + hdr_sz; if (wil->brd_info[i].file_max_size && hdr_sz > wil->brd_info[i].file_max_size) return -EINVAL; if (sizeof(*hdr) + hdr_sz > size) return -EINVAL; Loading @@ -692,7 +744,8 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, } type = le16_to_cpu(hdr->type); if (type != wil_fw_type_data) { wil_err_fw(wil, "invalid record type for board file: %d\n", wil_err_fw(wil, "invalid record type for board file: %d\n", type); return -EINVAL; } Loading @@ -701,15 +754,31 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data, return -EINVAL; } wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n", wil->brd_file_addr); wil_dbg_fw(wil, "using info from fw file for record %d: addr[0x%08x], max size %d\n", i, wil->brd_info[i].file_addr, wil->brd_info[i].file_max_size); rc = __fw_handle_data(wil, &hdr[1], hdr_sz, cpu_to_le32(wil->brd_file_addr)); cpu_to_le32(wil->brd_info[i].file_addr)); if (rc) return rc; } if (size) { wil_err_fw(wil, "unprocessed bytes: %zu\n", size); if (size >= sizeof(*hdr)) { wil_err_fw(wil, "Stop at offset %ld record type %d [%zd bytes]\n", (long)((const void *)hdr - data), le16_to_cpu(hdr->type), hdr_sz); } return -EINVAL; } return 0; } /** * wil_request_board - Request board file * Loading Loading @@ -738,7 +807,8 @@ int wil_request_board(struct wil6210_priv *wil, const char *name) rc = dlen; goto out; } /* Process the data record */ /* Process the data records */ rc = wil_brd_process(wil, brd->data, dlen); out: Loading
drivers/net/wireless/ath/wil6210/main.c +2 −1 Original line number Diff line number Diff line Loading @@ -860,6 +860,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) destroy_workqueue(wil->wq_service); destroy_workqueue(wil->wmi_wq); kfree(wil->board_file); kfree(wil->brd_info); } static void wil_shutdown_bl(struct wil6210_priv *wil) Loading Loading @@ -1760,7 +1761,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil_request_firmware(wil, wil->wil_fw_name, true); if (rc) goto out; if (wil->brd_file_addr) if (wil->num_of_brd_entries) rc = wil_request_board(wil, board_file); else rc = wil_request_firmware(wil, board_file, true); Loading
drivers/net/wireless/ath/wil6210/pcie_bus.c +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ int wil_set_capabilities(struct wil6210_priv *wil) min(sizeof(wil->platform_capa), sizeof(platform_capa))); } wil_info(wil, "platform_capa 0x%lx\n", *wil->platform_capa); /* extract FW capabilities from file without loading the FW */ wil_request_firmware(wil, wil->wil_fw_name, false); wil_refresh_fw_capabilities(wil); Loading
drivers/net/wireless/ath/wil6210/txrx.c +3 −0 Original line number Diff line number Diff line Loading @@ -1782,6 +1782,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, } } if (!_desc) goto mem_error; /* first descriptor may also be the last. * in this case d pointer is invalid */ Loading