diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:12:45 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:13:24 -0500 |
commit | 1032c736e81cdf490ae62f86da7efe67c3c3e61d (patch) | |
tree | a0c3919849f97dbbc5ea7c6a9ac1d7a639e44a73 /drivers/net/wireless/ath/carl9170 | |
parent | 117ff42fd43e92d24c6aa6f3e4f0f1e1edada140 (diff) | |
parent | cb00ec382b57d35b955c085198cd54a0c1fcdc94 (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.c | 97 |
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 | ||
149 | static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | 149 | static 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); | 206 | static 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 | |||
223 | static 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 | ||
339 | static struct carl9170fw_desc_head * | 362 | static struct carl9170fw_desc_head * |