aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-20 11:29:59 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-07-20 11:42:14 -0400
commit72dd2b2a44d82118714e0821fa16c65f9e40eb00 (patch)
tree1f52deaa7b8ef3ed933739a50be2a877a06544c9 /drivers/bluetooth
parentd1d588c181e35d98113f91c8004f77cdac2bf9d5 (diff)
Bluetooth: Fix endian and alignment issue with ath3k version handling
The ath3k driver is treating the version information badly when it comes to loading the right firmware version and comparing that it actually matches with the hardware. Initially this showed up as this: CHECK drivers/bluetooth/ath3k.c drivers/bluetooth/ath3k.c:373:17: warning: cast to restricted __le32 drivers/bluetooth/ath3k.c:435:17: warning: cast to restricted __le32 However when fixing this by actually using __packed and __le32 for the ath3_version structure, more issues came up: CHECK drivers/bluetooth/ath3k.c drivers/bluetooth/ath3k.c:381:32: warning: incorrect type in assignment (different base types) drivers/bluetooth/ath3k.c:381:32: expected restricted __le32 [usertype] rom_version drivers/bluetooth/ath3k.c:381:32: got int [signed] <noident> drivers/bluetooth/ath3k.c:382:34: warning: incorrect type in assignment (different base types) drivers/bluetooth/ath3k.c:382:34: expected restricted __le32 [usertype] build_version drivers/bluetooth/ath3k.c:382:34: got int [signed] <noident> drivers/bluetooth/ath3k.c:386:28: warning: restricted __le32 degrades to integer drivers/bluetooth/ath3k.c:386:56: warning: restricted __le32 degrades to integer This patch fixes every instance of the firmware version handling and makes sure it is endian safe and uses proper unaligned access. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/ath3k.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 230c552daf91..a0d7355ef127 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -27,6 +27,7 @@
27#include <linux/device.h> 27#include <linux/device.h>
28#include <linux/firmware.h> 28#include <linux/firmware.h>
29#include <linux/usb.h> 29#include <linux/usb.h>
30#include <asm/unaligned.h>
30#include <net/bluetooth/bluetooth.h> 31#include <net/bluetooth/bluetooth.h>
31 32
32#define VERSION "1.0" 33#define VERSION "1.0"
@@ -50,12 +51,12 @@
50#define ATH3K_NAME_LEN 0xFF 51#define ATH3K_NAME_LEN 0xFF
51 52
52struct ath3k_version { 53struct ath3k_version {
53 unsigned int rom_version; 54 __le32 rom_version;
54 unsigned int build_version; 55 __le32 build_version;
55 unsigned int ram_version; 56 __le32 ram_version;
56 unsigned char ref_clock; 57 __u8 ref_clock;
57 unsigned char reserved[0x07]; 58 __u8 reserved[7];
58}; 59} __packed;
59 60
60static const struct usb_device_id ath3k_table[] = { 61static const struct usb_device_id ath3k_table[] = {
61 /* Atheros AR3011 */ 62 /* Atheros AR3011 */
@@ -349,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev)
349 unsigned char fw_state; 350 unsigned char fw_state;
350 char filename[ATH3K_NAME_LEN] = {0}; 351 char filename[ATH3K_NAME_LEN] = {0};
351 const struct firmware *firmware; 352 const struct firmware *firmware;
352 struct ath3k_version fw_version, pt_version; 353 struct ath3k_version fw_version;
354 __u32 pt_rom_version, pt_build_version;
353 int ret; 355 int ret;
354 356
355 ret = ath3k_get_state(udev, &fw_state); 357 ret = ath3k_get_state(udev, &fw_state);
@@ -370,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev)
370 } 372 }
371 373
372 snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", 374 snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
373 le32_to_cpu(fw_version.rom_version)); 375 le32_to_cpu(fw_version.rom_version));
374 376
375 ret = request_firmware(&firmware, filename, &udev->dev); 377 ret = request_firmware(&firmware, filename, &udev->dev);
376 if (ret < 0) { 378 if (ret < 0) {
@@ -378,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev)
378 return ret; 380 return ret;
379 } 381 }
380 382
381 pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); 383 pt_rom_version = get_unaligned_le32(firmware->data +
382 pt_version.build_version = *(int *) 384 firmware->size - 8);
383 (firmware->data + firmware->size - 4); 385 pt_build_version = get_unaligned_le32(firmware->data +
386 firmware->size - 4);
384 387
385 if ((pt_version.rom_version != fw_version.rom_version) || 388 if (pt_rom_version != le32_to_cpu(fw_version.rom_version) ||
386 (pt_version.build_version <= fw_version.build_version)) { 389 pt_build_version <= le32_to_cpu(fw_version.build_version)) {
387 BT_ERR("Patch file version did not match with firmware"); 390 BT_ERR("Patch file version did not match with firmware");
388 release_firmware(firmware); 391 release_firmware(firmware);
389 return -EINVAL; 392 return -EINVAL;