]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
[media] af9035: do not use buffers from stack for usb_bulk_msg()
authorAntti Palosaari <crope@iki.fi>
Tue, 26 Feb 2013 16:56:34 +0000 (13:56 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 18 Mar 2013 19:53:33 +0000 (16:53 -0300)
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/af9035.h

index d3cb8d55febc5e3337f4430687fb3b7cde8a52fc..66f65197c40d26ffa88695d0bc47e843d486297a 100644 (file)
@@ -41,43 +41,45 @@ static u16 af9035_checksum(const u8 *buf, size_t len)
 
 static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
 {
-#define BUF_LEN 64
 #define REQ_HDR_LEN 4 /* send header size */
 #define ACK_HDR_LEN 3 /* rece header size */
 #define CHECKSUM_LEN 2
 #define USB_TIMEOUT 2000
        struct state *state = d_to_priv(d);
        int ret, wlen, rlen;
-       u8 buf[BUF_LEN];
        u16 checksum, tmp_checksum;
 
+       mutex_lock(&d->usb_mutex);
+
        /* buffer overflow check */
        if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
                        req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
                dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n",
                                __func__, req->wlen, req->rlen);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err;
        }
 
-       buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
-       buf[1] = req->mbox;
-       buf[2] = req->cmd;
-       buf[3] = state->seq++;
-       memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen);
+       state->buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
+       state->buf[1] = req->mbox;
+       state->buf[2] = req->cmd;
+       state->buf[3] = state->seq++;
+       memcpy(&state->buf[REQ_HDR_LEN], req->wbuf, req->wlen);
 
        wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN;
        rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
 
        /* calc and add checksum */
-       checksum = af9035_checksum(buf, buf[0] - 1);
-       buf[buf[0] - 1] = (checksum >> 8);
-       buf[buf[0] - 0] = (checksum & 0xff);
+       checksum = af9035_checksum(state->buf, state->buf[0] - 1);
+       state->buf[state->buf[0] - 1] = (checksum >> 8);
+       state->buf[state->buf[0] - 0] = (checksum & 0xff);
 
        /* no ack for these packets */
        if (req->cmd == CMD_FW_DL)
                rlen = 0;
 
-       ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
+       ret = dvb_usbv2_generic_rw_locked(d,
+                       state->buf, wlen, state->buf, rlen);
        if (ret)
                goto err;
 
@@ -86,8 +88,8 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
                goto exit;
 
        /* verify checksum */
-       checksum = af9035_checksum(buf, rlen - 2);
-       tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1];
+       checksum = af9035_checksum(state->buf, rlen - 2);
+       tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1];
        if (tmp_checksum != checksum) {
                dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \
                                "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd,
@@ -97,23 +99,21 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
        }
 
        /* check status */
-       if (buf[2]) {
+       if (state->buf[2]) {
                dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n",
-                               __func__, req->cmd, buf[2]);
+                               __func__, req->cmd, state->buf[2]);
                ret = -EIO;
                goto err;
        }
 
        /* read request, copy returned data to return buf */
        if (req->rlen)
-               memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
-
+               memcpy(req->rbuf, &state->buf[ACK_HDR_LEN], req->rlen);
 exit:
-       return 0;
-
 err:
-       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
-
+       mutex_unlock(&d->usb_mutex);
+       if (ret)
+               dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
index 29f3eec22c2c6be7f787219bb917d46cbf2dab0f..6d098a93d5ab33c0ffe27297f9c25b2bc1f28dc9 100644 (file)
@@ -52,6 +52,8 @@ struct usb_req {
 };
 
 struct state {
+#define BUF_LEN 64
+       u8 buf[BUF_LEN];
        u8 seq; /* packet sequence number */
        bool dual_mode;
        struct af9033_config af9033_config[2];