diff options
author | Johan Hovold <jhovold@gmail.com> | 2014-04-25 09:23:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-25 12:34:10 -0400 |
commit | 5509076d1b4485ce9fb07705fcbcd2695907ab5b (patch) | |
tree | 8b60716a6f575040d3cc10d97d97fb891a9b9f18 /drivers/usb | |
parent | 01bb59ebffdec314da8da66266edf29529372f9b (diff) |
USB: io_ti: fix firmware download on big-endian machines
During firmware download the device expects memory addresses in
big-endian byte order. As the wIndex parameter which hold the address is
sent in little-endian byte order regardless of host byte order, we need
to use swab16 rather than cpu_to_be16.
Also make sure to handle the struct ti_i2c_desc size parameter which is
returned in little-endian byte order.
Reported-by: Ludovic Drolez <ldrolez@debian.org>
Tested-by: Ludovic Drolez <ldrolez@debian.org>
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/io_ti.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2db5be9c305..df90dae53eb9 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/serial.h> | 30 | #include <linux/serial.h> |
31 | #include <linux/swab.h> | ||
31 | #include <linux/kfifo.h> | 32 | #include <linux/kfifo.h> |
32 | #include <linux/ioctl.h> | 33 | #include <linux/ioctl.h> |
33 | #include <linux/firmware.h> | 34 | #include <linux/firmware.h> |
@@ -280,7 +281,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, | |||
280 | { | 281 | { |
281 | int status = 0; | 282 | int status = 0; |
282 | __u8 read_length; | 283 | __u8 read_length; |
283 | __be16 be_start_address; | 284 | u16 be_start_address; |
284 | 285 | ||
285 | dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); | 286 | dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); |
286 | 287 | ||
@@ -296,10 +297,14 @@ static int read_download_mem(struct usb_device *dev, int start_address, | |||
296 | if (read_length > 1) { | 297 | if (read_length > 1) { |
297 | dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length); | 298 | dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length); |
298 | } | 299 | } |
299 | be_start_address = cpu_to_be16(start_address); | 300 | /* |
301 | * NOTE: Must use swab as wIndex is sent in little-endian | ||
302 | * byte order regardless of host byte order. | ||
303 | */ | ||
304 | be_start_address = swab16((u16)start_address); | ||
300 | status = ti_vread_sync(dev, UMPC_MEMORY_READ, | 305 | status = ti_vread_sync(dev, UMPC_MEMORY_READ, |
301 | (__u16)address_type, | 306 | (__u16)address_type, |
302 | (__force __u16)be_start_address, | 307 | be_start_address, |
303 | buffer, read_length); | 308 | buffer, read_length); |
304 | 309 | ||
305 | if (status) { | 310 | if (status) { |
@@ -394,7 +399,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, | |||
394 | struct device *dev = &serial->serial->dev->dev; | 399 | struct device *dev = &serial->serial->dev->dev; |
395 | int status = 0; | 400 | int status = 0; |
396 | int write_length; | 401 | int write_length; |
397 | __be16 be_start_address; | 402 | u16 be_start_address; |
398 | 403 | ||
399 | /* We can only send a maximum of 1 aligned byte page at a time */ | 404 | /* We can only send a maximum of 1 aligned byte page at a time */ |
400 | 405 | ||
@@ -409,11 +414,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, | |||
409 | __func__, start_address, write_length); | 414 | __func__, start_address, write_length); |
410 | usb_serial_debug_data(dev, __func__, write_length, buffer); | 415 | usb_serial_debug_data(dev, __func__, write_length, buffer); |
411 | 416 | ||
412 | /* Write first page */ | 417 | /* |
413 | be_start_address = cpu_to_be16(start_address); | 418 | * Write first page. |
419 | * | ||
420 | * NOTE: Must use swab as wIndex is sent in little-endian byte order | ||
421 | * regardless of host byte order. | ||
422 | */ | ||
423 | be_start_address = swab16((u16)start_address); | ||
414 | status = ti_vsend_sync(serial->serial->dev, | 424 | status = ti_vsend_sync(serial->serial->dev, |
415 | UMPC_MEMORY_WRITE, (__u16)address_type, | 425 | UMPC_MEMORY_WRITE, (__u16)address_type, |
416 | (__force __u16)be_start_address, | 426 | be_start_address, |
417 | buffer, write_length); | 427 | buffer, write_length); |
418 | if (status) { | 428 | if (status) { |
419 | dev_dbg(dev, "%s - ERROR %d\n", __func__, status); | 429 | dev_dbg(dev, "%s - ERROR %d\n", __func__, status); |
@@ -436,11 +446,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, | |||
436 | __func__, start_address, write_length); | 446 | __func__, start_address, write_length); |
437 | usb_serial_debug_data(dev, __func__, write_length, buffer); | 447 | usb_serial_debug_data(dev, __func__, write_length, buffer); |
438 | 448 | ||
439 | /* Write next page */ | 449 | /* |
440 | be_start_address = cpu_to_be16(start_address); | 450 | * Write next page. |
451 | * | ||
452 | * NOTE: Must use swab as wIndex is sent in little-endian byte | ||
453 | * order regardless of host byte order. | ||
454 | */ | ||
455 | be_start_address = swab16((u16)start_address); | ||
441 | status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, | 456 | status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, |
442 | (__u16)address_type, | 457 | (__u16)address_type, |
443 | (__force __u16)be_start_address, | 458 | be_start_address, |
444 | buffer, write_length); | 459 | buffer, write_length); |
445 | if (status) { | 460 | if (status) { |
446 | dev_err(dev, "%s - ERROR %d\n", __func__, status); | 461 | dev_err(dev, "%s - ERROR %d\n", __func__, status); |
@@ -585,8 +600,8 @@ static int get_descriptor_addr(struct edgeport_serial *serial, | |||
585 | if (rom_desc->Type == desc_type) | 600 | if (rom_desc->Type == desc_type) |
586 | return start_address; | 601 | return start_address; |
587 | 602 | ||
588 | start_address = start_address + sizeof(struct ti_i2c_desc) | 603 | start_address = start_address + sizeof(struct ti_i2c_desc) + |
589 | + rom_desc->Size; | 604 | le16_to_cpu(rom_desc->Size); |
590 | 605 | ||
591 | } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); | 606 | } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); |
592 | 607 | ||
@@ -599,7 +614,7 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer) | |||
599 | __u16 i; | 614 | __u16 i; |
600 | __u8 cs = 0; | 615 | __u8 cs = 0; |
601 | 616 | ||
602 | for (i = 0; i < rom_desc->Size; i++) | 617 | for (i = 0; i < le16_to_cpu(rom_desc->Size); i++) |
603 | cs = (__u8)(cs + buffer[i]); | 618 | cs = (__u8)(cs + buffer[i]); |
604 | 619 | ||
605 | if (cs != rom_desc->CheckSum) { | 620 | if (cs != rom_desc->CheckSum) { |
@@ -650,7 +665,7 @@ static int check_i2c_image(struct edgeport_serial *serial) | |||
650 | break; | 665 | break; |
651 | 666 | ||
652 | if ((start_address + sizeof(struct ti_i2c_desc) + | 667 | if ((start_address + sizeof(struct ti_i2c_desc) + |
653 | rom_desc->Size) > TI_MAX_I2C_SIZE) { | 668 | le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) { |
654 | status = -ENODEV; | 669 | status = -ENODEV; |
655 | dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__); | 670 | dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__); |
656 | break; | 671 | break; |
@@ -665,7 +680,8 @@ static int check_i2c_image(struct edgeport_serial *serial) | |||
665 | /* Read the descriptor data */ | 680 | /* Read the descriptor data */ |
666 | status = read_rom(serial, start_address + | 681 | status = read_rom(serial, start_address + |
667 | sizeof(struct ti_i2c_desc), | 682 | sizeof(struct ti_i2c_desc), |
668 | rom_desc->Size, buffer); | 683 | le16_to_cpu(rom_desc->Size), |
684 | buffer); | ||
669 | if (status) | 685 | if (status) |
670 | break; | 686 | break; |
671 | 687 | ||
@@ -674,7 +690,7 @@ static int check_i2c_image(struct edgeport_serial *serial) | |||
674 | break; | 690 | break; |
675 | } | 691 | } |
676 | start_address = start_address + sizeof(struct ti_i2c_desc) + | 692 | start_address = start_address + sizeof(struct ti_i2c_desc) + |
677 | rom_desc->Size; | 693 | le16_to_cpu(rom_desc->Size); |
678 | 694 | ||
679 | } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && | 695 | } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && |
680 | (start_address < TI_MAX_I2C_SIZE)); | 696 | (start_address < TI_MAX_I2C_SIZE)); |
@@ -712,7 +728,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) | |||
712 | 728 | ||
713 | /* Read the descriptor data */ | 729 | /* Read the descriptor data */ |
714 | status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), | 730 | status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), |
715 | rom_desc->Size, buffer); | 731 | le16_to_cpu(rom_desc->Size), buffer); |
716 | if (status) | 732 | if (status) |
717 | goto exit; | 733 | goto exit; |
718 | 734 | ||