Skip to content

Commit

Permalink
V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB excha…
Browse files Browse the repository at this point in the history
…nges.

The USB buffer may be used for DMA and there may be a caching problem
if the buffer is part of the device structure.
Thanks to Alan Stern.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Jean-Francois Moine authored and Mauro Carvalho Chehab committed Sep 3, 2008
1 parent 91de65a commit 8295d99
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 140 deletions.
4 changes: 2 additions & 2 deletions drivers/media/video/gspca/conex.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;

#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
if (len > USB_BUF_SZ) {
err("reg_r: buffer overflow");
return;
}
Expand Down Expand Up @@ -164,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;

#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/media/video/gspca/etoms.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;

#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
if (len > USB_BUF_SZ) {
err("reg_r: buffer overflow");
return;
}
Expand Down Expand Up @@ -273,7 +273,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
struct usb_device *dev = gspca_dev->dev;

#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
Expand Down
8 changes: 8 additions & 0 deletions drivers/media/video/gspca/gspca.c
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,12 @@ int gspca_dev_probe(struct usb_interface *intf,
err("couldn't kzalloc gspca struct");
return -EIO;
}
gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
if (!gspca_dev->usb_buf) {
err("out of memory");
ret = -EIO;
goto out;
}
gspca_dev->dev = dev;
gspca_dev->iface = interface->bInterfaceNumber;
gspca_dev->nbalt = intf->num_altsetting;
Expand Down Expand Up @@ -1774,6 +1780,7 @@ int gspca_dev_probe(struct usb_interface *intf,
PDEBUG(D_PROBE, "probe ok");
return 0;
out:
kfree(gspca_dev->usb_buf);
kfree(gspca_dev);
return ret;
}
Expand Down Expand Up @@ -1806,6 +1813,7 @@ void gspca_disconnect(struct usb_interface *intf)
/* We don't want people trying to open up the device */
video_unregister_device(&gspca_dev->vdev);
/* Free the memory */
kfree(gspca_dev->usb_buf);
kfree(gspca_dev);
PDEBUG(D_PROBE, "disconnect complete");
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/media/video/gspca/gspca.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ struct gspca_dev {
const struct sd_desc *sd_desc; /* subdriver description */
unsigned ctrl_dis; /* disabled controls (bit map) */

__u8 usb_buf[8]; /* buffer for USB exchanges */
#define USB_BUF_SZ 64
__u8 *usb_buf; /* buffer for USB exchanges */
struct urb *urb[MAX_NURBS];

__u8 *frbuf; /* buffer for nframes */
Expand Down
21 changes: 1 addition & 20 deletions drivers/media/video/gspca/mars.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,6 @@ static int reg_w(struct gspca_dev *gspca_dev,
return rc;
}

static int reg_w_buf(struct gspca_dev *gspca_dev,
__u16 index, __u8 *buf, int len)
{
int rc;

rc = usb_control_msg(gspca_dev->dev,
usb_sndbulkpipe(gspca_dev->dev, 4),
0x12,
0xc8, /* ?? */
0, /* value */
index, buf, len, 500);
if (rc < 0)
PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
return rc;
}

static void bulk_w(struct gspca_dev *gspca_dev,
__u16 *pch,
__u16 Address)
Expand Down Expand Up @@ -175,7 +159,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
/*
Initialize the MR97113 chip register
*/
data = kmalloc(16, GFP_KERNEL);
data[0] = 0x00; /* address */
data[1] = 0x0c | 0x01; /* reg 0 */
data[2] = 0x01; /* reg 1 */
Expand All @@ -195,12 +178,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
data[10] = 0x5d; /* reg 9, I2C device address
* [for PAS5101 (0x40)] [for MI (0x5d)] */

err_code = reg_w_buf(gspca_dev, data[0], data, 11);
kfree(data);
err_code = reg_w(gspca_dev, data[0], 11);
if (err_code < 0)
return;

data = gspca_dev->usb_buf;
data[0] = 0x23; /* address */
data[1] = 0x09; /* reg 35, append frame header */

Expand Down
24 changes: 2 additions & 22 deletions drivers/media/video/gspca/sonixb.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
int len)
{
#ifdef GSPCA_DEBUG
if (len > sizeof gspca_dev->usb_buf) {
if (len > USB_BUF_SZ) {
PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
return;
}
Expand All @@ -426,26 +426,6 @@ static void reg_w(struct gspca_dev *gspca_dev,
500);
}

static void reg_w_big(struct gspca_dev *gspca_dev,
__u16 value,
const __u8 *buffer,
int len)
{
__u8 *tmpbuf;

tmpbuf = kmalloc(len, GFP_KERNEL);
memcpy(tmpbuf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0x08, /* request */
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value,
0, /* index */
tmpbuf, len,
500);
kfree(tmpbuf);
}

static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
{
int retry = 60;
Expand Down Expand Up @@ -886,7 +866,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg 0x17 SensorClk enable inv Clk 0x60 */
reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
/* Set the registers from the template */
reg_w_big(gspca_dev, 0x01, sn9c10x, l);
reg_w(gspca_dev, 0x01, sn9c10x, l);
switch (sd->sensor) {
case SENSOR_HV7131R:
i2c_w_vector(gspca_dev, hv7131_sensor_init,
Expand Down
43 changes: 20 additions & 23 deletions drivers/media/video/gspca/sonixj.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,10 +613,16 @@ static const __u8 qtable4[] = {
0x29, 0x29, 0x29, 0x29
};

/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
/* read <len> bytes to gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
__u16 value, int len)
{
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
err("reg_r: buffer overflow");
return;
}
#endif
usb_control_msg(gspca_dev->dev,
usb_rcvctrlpipe(gspca_dev->dev, 0),
0,
Expand Down Expand Up @@ -649,29 +655,20 @@ static void reg_w(struct gspca_dev *gspca_dev,
{
PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
value, buffer[0], buffer[1]);
if (len <= sizeof gspca_dev->usb_buf) {
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, 0,
gspca_dev->usb_buf, len,
500);
} else {
__u8 *tmpbuf;

tmpbuf = kmalloc(len, GFP_KERNEL);
memcpy(tmpbuf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, 0,
tmpbuf, len,
500);
kfree(tmpbuf);
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
#endif
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, 0,
gspca_dev->usb_buf, len,
500);
}

/* I2C write 1 byte */
Expand Down
Loading

0 comments on commit 8295d99

Please sign in to comment.