aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaya Erez <merez@codeaurora.org>2018-01-21 04:14:43 -0500
committerKalle Valo <kvalo@codeaurora.org>2018-01-25 00:32:37 -0500
commit81b35afa49c8bf1813c3b69b303d63e1b8ea6206 (patch)
treefe60b1cec81d2dc734538055db049ce180a82812
parent54fca595d1eec3d7d008b322a53a1ebed7f78193 (diff)
wil6210: support parsing brd file address from fw file
In order to allow using the same brd file across different 11ad chips, the address for loading the brd file should be part of the FW file, instead of the brd file. The brd file is expected to include only one section. To allow backward compatibility the driver reads the address from the brd file in case it is not included in the FW file. Signed-off-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.h18
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c167
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c7
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h3
4 files changed, 184 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h
index 2f2b910501ba..2c7b24f61587 100644
--- a/drivers/net/wireless/ath/wil6210/fw.h
+++ b/drivers/net/wireless/ath/wil6210/fw.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. 2 * Copyright (c) 2014,2016 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -58,15 +59,30 @@ struct wil_fw_record_comment { /* type == wil_fw_type_comment */
58 u8 data[0]; /* free-form data [data_size], see above */ 59 u8 data[0]; /* free-form data [data_size], see above */
59} __packed; 60} __packed;
60 61
62/* Comment header - common for all comment record types */
63struct wil_fw_record_comment_hdr {
64 __le32 magic;
65};
66
61/* FW capabilities encoded inside a comment record */ 67/* FW capabilities encoded inside a comment record */
62#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba) 68#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba)
63struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ 69struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */
64 /* identifies capabilities record */ 70 /* identifies capabilities record */
65 __le32 magic; 71 struct wil_fw_record_comment_hdr hdr;
66 /* capabilities (variable size), see enum wmi_fw_capability */ 72 /* capabilities (variable size), see enum wmi_fw_capability */
67 u8 capabilities[0]; 73 u8 capabilities[0];
68}; 74};
69 75
76/* brd file info encoded inside a comment record */
77#define WIL_BRD_FILE_MAGIC (0xabcddcbb)
78struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */
79 /* identifies brd file record */
80 struct wil_fw_record_comment_hdr hdr;
81 __le32 version;
82 __le32 base_addr;
83 __le32 max_size_bytes;
84} __packed;
85
70/* perform action 86/* perform action
71 * data_size = @head.size - offsetof(struct wil_fw_record_action, data) 87 * data_size = @head.size - offsetof(struct wil_fw_record_action, data)
72 */ 88 */
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index 77d1902947e3..914c0106e94b 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. 2 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -128,14 +129,13 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
128} 129}
129 130
130static int 131static int
131fw_handle_comment(struct wil6210_priv *wil, const void *data, 132fw_handle_capabilities(struct wil6210_priv *wil, const void *data,
132 size_t size) 133 size_t size)
133{ 134{
134 const struct wil_fw_record_capabilities *rec = data; 135 const struct wil_fw_record_capabilities *rec = data;
135 size_t capa_size; 136 size_t capa_size;
136 137
137 if (size < sizeof(*rec) || 138 if (size < sizeof(*rec)) {
138 le32_to_cpu(rec->magic) != WIL_FW_CAPABILITIES_MAGIC) {
139 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, 139 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
140 data, size, true); 140 data, size, true);
141 return 0; 141 return 0;
@@ -151,8 +151,56 @@ fw_handle_comment(struct wil6210_priv *wil, const void *data,
151 return 0; 151 return 0;
152} 152}
153 153
154static int fw_handle_data(struct wil6210_priv *wil, const void *data, 154static int
155 size_t size) 155fw_handle_brd_file(struct wil6210_priv *wil, const void *data,
156 size_t size)
157{
158 const struct wil_fw_record_brd_file *rec = data;
159
160 if (size < sizeof(*rec)) {
161 wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
162 data, size, true);
163 return 0;
164 }
165
166 wil->brd_file_addr = le32_to_cpu(rec->base_addr);
167 wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes);
168
169 wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n",
170 wil->brd_file_addr, wil->brd_file_max_size);
171
172 return 0;
173}
174
175static int
176fw_handle_comment(struct wil6210_priv *wil, const void *data,
177 size_t size)
178{
179 const struct wil_fw_record_comment_hdr *hdr = data;
180 u32 magic;
181 int rc = 0;
182
183 if (size < sizeof(*hdr))
184 return 0;
185
186 magic = le32_to_cpu(hdr->magic);
187
188 switch (magic) {
189 case WIL_FW_CAPABILITIES_MAGIC:
190 wil_dbg_fw(wil, "magic is WIL_FW_CAPABILITIES_MAGIC\n");
191 rc = fw_handle_capabilities(wil, data, size);
192 break;
193 case WIL_BRD_FILE_MAGIC:
194 wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n");
195 rc = fw_handle_brd_file(wil, data, size);
196 break;
197 }
198
199 return rc;
200}
201
202static int __fw_handle_data(struct wil6210_priv *wil, const void *data,
203 size_t size, __le32 addr)
156{ 204{
157 const struct wil_fw_record_data *d = data; 205 const struct wil_fw_record_data *d = data;
158 void __iomem *dst; 206 void __iomem *dst;
@@ -163,16 +211,23 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data,
163 return -EINVAL; 211 return -EINVAL;
164 } 212 }
165 213
166 if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) 214 if (!wil_fw_addr_check(wil, &dst, addr, s, "address"))
167 return -EINVAL; 215 return -EINVAL;
168 wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), 216 wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(addr), s);
169 s);
170 wil_memcpy_toio_32(dst, d->data, s); 217 wil_memcpy_toio_32(dst, d->data, s);
171 wmb(); /* finish before processing next record */ 218 wmb(); /* finish before processing next record */
172 219
173 return 0; 220 return 0;
174} 221}
175 222
223static int fw_handle_data(struct wil6210_priv *wil, const void *data,
224 size_t size)
225{
226 const struct wil_fw_record_data *d = data;
227
228 return __fw_handle_data(wil, data, size, d->addr);
229}
230
176static int fw_handle_fill(struct wil6210_priv *wil, const void *data, 231static int fw_handle_fill(struct wil6210_priv *wil, const void *data,
177 size_t size) 232 size_t size)
178{ 233{
@@ -552,6 +607,100 @@ out:
552} 607}
553 608
554/** 609/**
610 * wil_brd_process - process section from BRD file
611 *
612 * Return error code
613 */
614static int wil_brd_process(struct wil6210_priv *wil, const void *data,
615 size_t size)
616{
617 int rc = 0;
618 const struct wil_fw_record_head *hdr = data;
619 size_t s, hdr_sz;
620 u16 type;
621
622 /* Assuming the board file includes only one header record and one data
623 * record. Each record starts with wil_fw_record_head.
624 */
625 if (size < sizeof(*hdr))
626 return -EINVAL;
627 s = sizeof(*hdr) + le32_to_cpu(hdr->size);
628 if (s > size)
629 return -EINVAL;
630
631 /* Skip the header record and handle the data record */
632 hdr = (const void *)hdr + s;
633 size -= s;
634 if (size < sizeof(*hdr))
635 return -EINVAL;
636 hdr_sz = le32_to_cpu(hdr->size);
637
638 if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size)
639 return -EINVAL;
640 if (sizeof(*hdr) + hdr_sz > size)
641 return -EINVAL;
642 if (hdr_sz % 4) {
643 wil_err_fw(wil, "unaligned record size: %zu\n",
644 hdr_sz);
645 return -EINVAL;
646 }
647 type = le16_to_cpu(hdr->type);
648 if (type != wil_fw_type_data) {
649 wil_err_fw(wil, "invalid record type for board file: %d\n",
650 type);
651 return -EINVAL;
652 }
653 if (hdr_sz < sizeof(struct wil_fw_record_data)) {
654 wil_err_fw(wil, "data record too short: %zu\n", hdr_sz);
655 return -EINVAL;
656 }
657
658 wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n",
659 wil->brd_file_addr);
660
661 rc = __fw_handle_data(wil, &hdr[1], hdr_sz,
662 cpu_to_le32(wil->brd_file_addr));
663
664 return rc;
665}
666
667/**
668 * wil_request_board - Request board file
669 *
670 * Request board image from the file
671 * board file address and max size are read from FW file
672 * during initialization.
673 * brd file shall include one header and one data section.
674 *
675 * Return error code
676 */
677int wil_request_board(struct wil6210_priv *wil, const char *name)
678{
679 int rc, dlen;
680 const struct firmware *brd;
681
682 rc = request_firmware(&brd, name, wil_to_dev(wil));
683 if (rc) {
684 wil_err_fw(wil, "Failed to load brd %s\n", name);
685 return rc;
686 }
687 wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, brd->size);
688
689 /* Verify the header */
690 dlen = wil_fw_verify(wil, brd->data, brd->size);
691 if (dlen < 0) {
692 rc = dlen;
693 goto out;
694 }
695 /* Process the data record */
696 rc = wil_brd_process(wil, brd->data, dlen);
697
698out:
699 release_firmware(brd);
700 return rc;
701}
702
703/**
555 * wil_fw_verify_file_exists - checks if firmware file exist 704 * wil_fw_verify_file_exists - checks if firmware file exist
556 * 705 *
557 * @wil: driver context 706 * @wil: driver context
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 575aafe149a6..0c61a6c13991 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1262,7 +1262,12 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
1262 rc = wil_request_firmware(wil, wil->wil_fw_name, true); 1262 rc = wil_request_firmware(wil, wil->wil_fw_name, true);
1263 if (rc) 1263 if (rc)
1264 goto out; 1264 goto out;
1265 rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true); 1265 if (wil->brd_file_addr)
1266 rc = wil_request_board(wil, WIL_BOARD_FILE_NAME);
1267 else
1268 rc = wil_request_firmware(wil,
1269 WIL_BOARD_FILE_NAME,
1270 true);
1266 if (rc) 1271 if (rc)
1267 goto out; 1272 goto out;
1268 1273
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 836122afb091..0df2aada6659 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -681,6 +681,8 @@ struct wil6210_priv {
681 const char *hw_name; 681 const char *hw_name;
682 const char *wil_fw_name; 682 const char *wil_fw_name;
683 char *board_file; 683 char *board_file;
684 u32 brd_file_addr;
685 u32 brd_file_max_size;
684 DECLARE_BITMAP(hw_capa, hw_capa_last); 686 DECLARE_BITMAP(hw_capa, hw_capa_last);
685 DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); 687 DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX);
686 DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX); 688 DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX);
@@ -1053,6 +1055,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type);
1053 1055
1054int wil_request_firmware(struct wil6210_priv *wil, const char *name, 1056int wil_request_firmware(struct wil6210_priv *wil, const char *name,
1055 bool load); 1057 bool load);
1058int wil_request_board(struct wil6210_priv *wil, const char *name);
1056bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); 1059bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
1057 1060
1058void wil_pm_runtime_allow(struct wil6210_priv *wil); 1061void wil_pm_runtime_allow(struct wil6210_priv *wil);