aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-01-05 10:12:45 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-01-05 10:13:24 -0500
commit1032c736e81cdf490ae62f86da7efe67c3c3e61d (patch)
treea0c3919849f97dbbc5ea7c6a9ac1d7a639e44a73 /drivers/net/wireless/ath/carl9170
parent117ff42fd43e92d24c6aa6f3e4f0f1e1edada140 (diff)
parentcb00ec382b57d35b955c085198cd54a0c1fcdc94 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: drivers/net/wireless/b43legacy/dma.c
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c97
1 files changed, 60 insertions, 37 deletions
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index cba9d0435dc4..3de61adacd34 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -146,13 +146,15 @@ static bool valid_cpu_addr(const u32 address)
146 return false; 146 return false;
147} 147}
148 148
149static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) 149static int carl9170_fw_checksum(struct ar9170 *ar, const __u8 *data,
150 size_t len)
150{ 151{
151 const struct carl9170fw_otus_desc *otus_desc; 152 const struct carl9170fw_otus_desc *otus_desc;
152 const struct carl9170fw_chk_desc *chk_desc;
153 const struct carl9170fw_last_desc *last_desc; 153 const struct carl9170fw_last_desc *last_desc;
154 const struct carl9170fw_txsq_desc *txsq_desc; 154 const struct carl9170fw_chk_desc *chk_desc;
155 u16 if_comb_types; 155 unsigned long fin, diff;
156 unsigned int dsc_len;
157 u32 crc32;
156 158
157 last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, 159 last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
158 sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); 160 sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
@@ -170,36 +172,68 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
170 chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC, 172 chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC,
171 sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER); 173 sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER);
172 174
173 if (chk_desc) { 175 if (!chk_desc) {
174 unsigned long fin, diff; 176 dev_warn(&ar->udev->dev, "Unprotected firmware image.\n");
175 unsigned int dsc_len; 177 return 0;
176 u32 crc32; 178 }
177 179
178 dsc_len = min_t(unsigned int, len, 180 dsc_len = min_t(unsigned int, len,
179 (unsigned long)chk_desc - (unsigned long)otus_desc); 181 (unsigned long)chk_desc - (unsigned long)otus_desc);
180 182
181 fin = (unsigned long) last_desc + sizeof(*last_desc); 183 fin = (unsigned long) last_desc + sizeof(*last_desc);
182 diff = fin - (unsigned long) otus_desc; 184 diff = fin - (unsigned long) otus_desc;
183 185
184 if (diff < len) 186 if (diff < len)
185 len -= diff; 187 len -= diff;
186 188
187 if (len < 256) 189 if (len < 256)
188 return -EIO; 190 return -EIO;
189 191
190 crc32 = crc32_le(~0, data, len); 192 crc32 = crc32_le(~0, data, len);
191 if (cpu_to_le32(crc32) != chk_desc->fw_crc32) { 193 if (cpu_to_le32(crc32) != chk_desc->fw_crc32) {
192 dev_err(&ar->udev->dev, "fw checksum test failed.\n"); 194 dev_err(&ar->udev->dev, "fw checksum test failed.\n");
193 return -ENOEXEC; 195 return -ENOEXEC;
194 } 196 }
197
198 crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len);
199 if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) {
200 dev_err(&ar->udev->dev, "descriptor check failed.\n");
201 return -EINVAL;
202 }
203 return 0;
204}
195 205
196 crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len); 206static int carl9170_fw_tx_sequence(struct ar9170 *ar)
197 if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) { 207{
198 dev_err(&ar->udev->dev, "descriptor check failed.\n"); 208 const struct carl9170fw_txsq_desc *txsq_desc;
209
210 txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, sizeof(*txsq_desc),
211 CARL9170FW_TXSQ_DESC_CUR_VER);
212 if (txsq_desc) {
213 ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
214 if (!valid_cpu_addr(ar->fw.tx_seq_table))
199 return -EINVAL; 215 return -EINVAL;
200 }
201 } else { 216 } else {
202 dev_warn(&ar->udev->dev, "Unprotected firmware image.\n"); 217 ar->fw.tx_seq_table = 0;
218 }
219
220 return 0;
221}
222
223static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
224{
225 const struct carl9170fw_otus_desc *otus_desc;
226 int err;
227 u16 if_comb_types;
228
229 err = carl9170_fw_checksum(ar, data, len);
230 if (err)
231 return err;
232
233 otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
234 sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
235 if (!otus_desc) {
236 return -ENODATA;
203 } 237 }
204 238
205#define SUPP(feat) \ 239#define SUPP(feat) \
@@ -321,19 +355,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
321 355
322 ar->hw->wiphy->interface_modes |= if_comb_types; 356 ar->hw->wiphy->interface_modes |= if_comb_types;
323 357
324 txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC,
325 sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER);
326
327 if (txsq_desc) {
328 ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
329 if (!valid_cpu_addr(ar->fw.tx_seq_table))
330 return -EINVAL;
331 } else {
332 ar->fw.tx_seq_table = 0;
333 }
334
335#undef SUPPORTED 358#undef SUPPORTED
336 return 0; 359 return carl9170_fw_tx_sequence(ar);
337} 360}
338 361
339static struct carl9170fw_desc_head * 362static struct carl9170fw_desc_head *