USB: cypress_m8: use put_unaligned_le32() where necessary
[pandora-kernel.git] / drivers / usb / serial / cypress_m8.c
index 60c2002..b19e16a 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/serial.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
+#include <asm/unaligned.h>
 
 #include "cypress_m8.h"
 
@@ -344,7 +345,8 @@ static int cypress_serial_control(struct tty_struct *tty,
 {
        int new_baudrate = 0, retval = 0, tries = 0;
        struct cypress_private *priv;
-       __u8 feature_buffer[5];
+       u8 *feature_buffer;
+       const unsigned int feature_len = 5;
        unsigned long flags;
 
        dbg("%s", __func__);
@@ -354,6 +356,10 @@ static int cypress_serial_control(struct tty_struct *tty,
        if (!priv->comm_is_ok)
                return -ENODEV;
 
+       feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL);
+       if (!feature_buffer)
+               return -ENOMEM;
+
        switch (cypress_request_type) {
        case CYPRESS_SET_CONFIG:
                /* 0 means 'Hang up' so doesn't change the true bit rate */
@@ -370,9 +376,8 @@ static int cypress_serial_control(struct tty_struct *tty,
                dbg("%s - baud rate is being sent as %d",
                                        __func__, new_baudrate);
 
-               memset(feature_buffer, 0, sizeof(feature_buffer));
                /* fill the feature_buffer with new configuration */
-               *((u_int32_t *)feature_buffer) = new_baudrate;
+               put_unaligned_le32(new_baudrate, feature_buffer);
                feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
                /* 1 bit gap */
                feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
@@ -394,15 +399,15 @@ static int cypress_serial_control(struct tty_struct *tty,
                                        HID_REQ_SET_REPORT,
                                        USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
                                        0x0300, 0, feature_buffer,
-                                       sizeof(feature_buffer), 500);
+                                       feature_len, 500);
 
                        if (tries++ >= 3)
                                break;
 
-               } while (retval != sizeof(feature_buffer) &&
+               } while (retval != feature_len &&
                         retval != -ENODEV);
 
-               if (retval != sizeof(feature_buffer)) {
+               if (retval != feature_len) {
                        dev_err(&port->dev, "%s - failed sending serial "
                                "line settings - %d\n", __func__, retval);
                        cypress_set_dead(port);
@@ -422,43 +427,42 @@ static int cypress_serial_control(struct tty_struct *tty,
                        /* Not implemented for this device,
                           and if we try to do it we're likely
                           to crash the hardware. */
-                       return -ENOTTY;
+                       retval = -ENOTTY;
+                       goto out;
                }
                dbg("%s - retreiving serial line settings", __func__);
-               /* set initial values in feature buffer */
-               memset(feature_buffer, 0, sizeof(feature_buffer));
-
                do {
                        retval = usb_control_msg(port->serial->dev,
                                        usb_rcvctrlpipe(port->serial->dev, 0),
                                        HID_REQ_GET_REPORT,
                                        USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
                                        0x0300, 0, feature_buffer,
-                                       sizeof(feature_buffer), 500);
+                                       feature_len, 500);
 
                        if (tries++ >= 3)
                                break;
-               } while (retval != sizeof(feature_buffer)
+               } while (retval != feature_len
                                                && retval != -ENODEV);
 
-               if (retval != sizeof(feature_buffer)) {
+               if (retval != feature_len) {
                        dev_err(&port->dev, "%s - failed to retrieve serial "
                                "line settings - %d\n", __func__, retval);
                        cypress_set_dead(port);
-                       return retval;
+                       goto out;
                } else {
                        spin_lock_irqsave(&priv->lock, flags);
                        /* store the config in one byte, and later
                           use bit masks to check values */
                        priv->current_config = feature_buffer[4];
-                       priv->baud_rate = *((u_int32_t *)feature_buffer);
+                       priv->baud_rate = get_unaligned_le32(feature_buffer);
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
        }
        spin_lock_irqsave(&priv->lock, flags);
        ++priv->cmd_count;
        spin_unlock_irqrestore(&priv->lock, flags);
-
+out:
+       kfree(feature_buffer);
        return retval;
 } /* cypress_serial_control */