This is a note to let you know that I've just added the patch titled USB: io_ti: fix firmware download on big-endian machines to the 3.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: usb-io_ti-fix-firmware-download-on-big-endian-machines.patch and it can be found in the queue-3.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 5509076d1b4485ce9fb07705fcbcd2695907ab5b Mon Sep 17 00:00:00 2001 From: Johan Hovold <jhovold@xxxxxxxxx> Date: Fri, 25 Apr 2014 15:23:03 +0200 Subject: USB: io_ti: fix firmware download on big-endian machines From: Johan Hovold <jhovold@xxxxxxxxx> commit 5509076d1b4485ce9fb07705fcbcd2695907ab5b upstream. 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@xxxxxxxxxx> Tested-by: Ludovic Drolez <ldrolez@xxxxxxxxxx> Signed-off-by: Johan Hovold <jhovold@xxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/serial/io_ti.c | 50 +++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 17 deletions(-) --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -29,6 +29,7 @@ #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/serial.h> +#include <linux/swab.h> #include <linux/kfifo.h> #include <linux/ioctl.h> #include <linux/firmware.h> @@ -298,7 +299,7 @@ static int read_download_mem(struct usb_ { int status = 0; __u8 read_length; - __be16 be_start_address; + u16 be_start_address; dbg("%s - @ %x for %d", __func__, start_address, length); @@ -315,10 +316,14 @@ static int read_download_mem(struct usb_ dbg("%s - @ %x for %d", __func__, start_address, read_length); } - be_start_address = cpu_to_be16(start_address); + /* + * NOTE: Must use swab as wIndex is sent in little-endian + * byte order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vread_sync(dev, UMPC_MEMORY_READ, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, read_length); if (status) { @@ -418,7 +423,7 @@ static int write_i2c_mem(struct edgeport { int status = 0; int write_length; - __be16 be_start_address; + u16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ @@ -434,11 +439,16 @@ static int write_i2c_mem(struct edgeport usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer); - /* Write first page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write first page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte order + * regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dbg("%s - ERROR %d", __func__, status); @@ -462,11 +472,16 @@ static int write_i2c_mem(struct edgeport usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer); - /* Write next page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write next page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte + * order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n", @@ -673,8 +688,8 @@ static int get_descriptor_addr(struct ed if (rom_desc->Type == desc_type) return start_address; - start_address = start_address + sizeof(struct ti_i2c_desc) - + rom_desc->Size; + start_address = start_address + sizeof(struct ti_i2c_desc) + + le16_to_cpu(rom_desc->Size); } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); @@ -687,7 +702,7 @@ static int valid_csum(struct ti_i2c_desc __u16 i; __u8 cs = 0; - for (i = 0; i < rom_desc->Size; i++) + for (i = 0; i < le16_to_cpu(rom_desc->Size); i++) cs = (__u8)(cs + buffer[i]); if (cs != rom_desc->CheckSum) { @@ -741,7 +756,7 @@ static int check_i2c_image(struct edgepo break; if ((start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size) > TI_MAX_I2C_SIZE) { + le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) { status = -ENODEV; dbg("%s - structure too big, erroring out.", __func__); break; @@ -756,7 +771,8 @@ static int check_i2c_image(struct edgepo /* Read the descriptor data */ status = read_rom(serial, start_address + sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), + buffer); if (status) break; @@ -765,7 +781,7 @@ static int check_i2c_image(struct edgepo break; } start_address = start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size; + le16_to_cpu(rom_desc->Size); } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); @@ -804,7 +820,7 @@ static int get_manuf_info(struct edgepor /* Read the descriptor data */ status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), buffer); if (status) goto exit; Patches currently in stable-queue which might be from jhovold@xxxxxxxxx are queue-3.4/usb-option-driver-add-support-for-telit-ue910v2.patch queue-3.4/usb-serial-ftdi_sio-add-id-for-brainboxes-serial-cards.patch queue-3.4/usb-cp210x-add-8281-nanotec-plug-drive.patch queue-3.4/revert-usb-serial-add-usbid-for-dell-wwan-card-to-sierra.c.patch queue-3.4/usb-io_ti-fix-firmware-download-on-big-endian-machines.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html