V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB exchanges.

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>
This commit is contained in:
Jean-Francois Moine 2008-09-03 17:12:19 -03:00 committed by Mauro Carvalho Chehab
parent 91de65ac00
commit 8295d99ee5
9 changed files with 116 additions and 140 deletions

View File

@ -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;
}
@ -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;
}

View File

@ -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;
}
@ -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;
}

View File

@ -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;
@ -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;
}
@ -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");
}

View File

@ -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 */

View File

@ -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)
@ -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 */
@ -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 */

View File

@ -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;
}
@ -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;
@ -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,

View File

@ -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,
@ -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 */

View File

@ -449,31 +449,47 @@ static const __u8 qtable_spca504_default[2][64] = {
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
};
static void reg_r(struct usb_device *dev,
__u16 req,
__u16 index,
__u8 *buffer, __u16 length)
/* read <len> bytes to gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
__u16 req,
__u16 index,
__u16 len)
{
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
#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),
req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
index, buffer, length,
index,
len ? gspca_dev->usb_buf : NULL, len,
500);
}
static void reg_w(struct usb_device *dev,
__u16 req,
__u16 value,
__u16 index,
__u8 *buffer, __u16 length)
/* write <len> bytes from gspca_dev->usb_buf */
static void reg_w(struct gspca_dev *gspca_dev,
__u16 req,
__u16 value,
__u16 index,
__u16 len)
{
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
err("reg_w: buffer overflow");
return;
}
#endif
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, buffer, length,
value, index,
len ? gspca_dev->usb_buf : NULL, len,
500);
}
@ -634,7 +650,7 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
int count = 10;
while (--count > 0) {
reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
reg_r(gspca_dev, 0x21, 0, 1);
if ((gspca_dev->usb_buf[0] & 0x01) == 0)
break;
msleep(10);
@ -644,15 +660,14 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
int count = 50;
while (--count > 0) {
reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
reg_r(gspca_dev, 0x21, 1, 1);
if (gspca_dev->usb_buf[0] != 0) {
gspca_dev->usb_buf[0] = 0;
reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
reg_w(gspca_dev, 0x21, 0, 1, 1);
reg_r(gspca_dev, 0x21, 1, 1);
spca504B_PollingDataReady(gspca_dev);
break;
}
@ -662,16 +677,14 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 *data;
data = kmalloc(64, GFP_KERNEL);
reg_r(dev, 0x20, 0, data, 5);
data = gspca_dev->usb_buf;
reg_r(gspca_dev, 0x20, 0, 5);
PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
data[0], data[1], data[2], data[3], data[4]);
reg_r(dev, 0x23, 0, data, 64);
reg_r(dev, 0x23, 1, data, 64);
kfree(data);
reg_r(gspca_dev, 0x23, 0, 64);
reg_r(gspca_dev, 0x23, 1, 64);
}
static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
@ -686,21 +699,21 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
Type = 0;
switch (sd->bridge) {
case BRIDGE_SPCA533:
reg_w(dev, 0x31, 0, 0, NULL, 0);
reg_w(gspca_dev, 0x31, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
spca50x_GetFirmware(gspca_dev);
gspca_dev->usb_buf[0] = 2; /* type */
reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
reg_w(gspca_dev, 0x24, 0, 8, 1);
reg_r(gspca_dev, 0x24, 8, 1);
gspca_dev->usb_buf[0] = Size;
reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
reg_w(gspca_dev, 0x25, 0, 4, 1);
reg_r(gspca_dev, 0x25, 4, 1); /* size */
rc = spca504B_PollingDataReady(gspca_dev);
/* Init the cam width height with some values get on init ? */
reg_w(dev, 0x31, 0, 4, NULL, 0);
reg_w(gspca_dev, 0x31, 0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
break;
@ -708,12 +721,12 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA504B: */
/* case BRIDGE_SPCA536: */
gspca_dev->usb_buf[0] = Size;
reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
reg_w(gspca_dev, 0x25, 0, 4, 1);
reg_r(gspca_dev, 0x25, 4, 1); /* size */
Type = 6;
gspca_dev->usb_buf[0] = Type;
reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
reg_w(gspca_dev, 0x27, 0, 0, 1);
reg_r(gspca_dev, 0x27, 0, 1); /* type */
rc = spca504B_PollingDataReady(gspca_dev);
break;
case BRIDGE_SPCA504:
@ -752,18 +765,15 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev)
static void spca504B_setQtable(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
gspca_dev->usb_buf[0] = 3;
reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
reg_w(gspca_dev, 0x26, 0, 0, 1);
reg_r(gspca_dev, 0x26, 0, 1);
spca504B_PollingDataReady(gspca_dev);
}
static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
int pollreg = 1;
switch (sd->bridge) {
@ -774,20 +784,20 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
default:
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA504B: */
reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
break;
case BRIDGE_SPCA536:
reg_w(dev, 0, 0, 0x20f0, NULL, 0);
reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
reg_w(dev, 0, 1, 0x20f4, NULL, 0);
reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
reg_w(dev, 0, 0, 0x2089, NULL, 0);
reg_w(gspca_dev, 0, 0, 0x20f0, 0);
reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
reg_w(gspca_dev, 0, 1, 0x20f4, 0);
reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
reg_w(gspca_dev, 0, 0, 0x2089, 0);
break;
}
if (pollreg)
@ -799,7 +809,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
struct cam *cam;
cam = &gspca_dev->cam;
@ -811,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
if (sd->subtype == AiptekMiniPenCam13) {
/* try to get the firmware as some cam answer 2.0.1.2.2
* and should be a spca504b then overwrite that setting */
reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
reg_r(gspca_dev, 0x20, 0, 1);
switch (gspca_dev->usb_buf[0]) {
case 1:
break; /* (right bridge/subtype) */
@ -860,12 +869,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
switch (sd->bridge) {
case BRIDGE_SPCA504B:
reg_w(dev, 0x1d, 0, 0, NULL, 0);
reg_w(dev, 0, 1, 0x2306, NULL, 0);
reg_w(dev, 0, 0, 0x0d04, NULL, 0);
reg_w(dev, 0, 0, 0x2000, NULL, 0);
reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
reg_w(dev, 0, 0, 0x2306, NULL, 0);
reg_w(gspca_dev, 0x1d, 0, 0, 0);
reg_w(gspca_dev, 0, 1, 0x2306, 0);
reg_w(gspca_dev, 0, 0, 0x0d04, 0);
reg_w(gspca_dev, 0, 0, 0x2000, 0);
reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
reg_w(gspca_dev, 0, 0, 0x2306, 0);
/* fall thru */
case BRIDGE_SPCA533:
rc = spca504B_PollingDataReady(gspca_dev);
@ -873,12 +882,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
break;
case BRIDGE_SPCA536:
spca50x_GetFirmware(gspca_dev);
reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
reg_r(gspca_dev, 0x00, 0x5002, 1);
gspca_dev->usb_buf[0] = 0;
reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
reg_w(gspca_dev, 0x24, 0, 0, 1);
reg_r(gspca_dev, 0x24, 0, 1);
rc = spca504B_PollingDataReady(gspca_dev);
reg_w(dev, 0x34, 0, 0, NULL, 0);
reg_w(gspca_dev, 0x34, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
break;
case BRIDGE_SPCA504C: /* pccam600 */
@ -971,12 +980,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA536: */
if (sd->subtype == MegapixV4 ||
sd->subtype == LogitechClickSmart820) {
reg_w(dev, 0xf0, 0, 0, NULL, 0);
reg_w(gspca_dev, 0xf0, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
reg_r(dev, 0xf0, 4, NULL, 0);
reg_r(gspca_dev, 0xf0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
} else {
reg_w(dev, 0x31, 0, 4, NULL, 0);
reg_w(gspca_dev, 0x31, 0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
}
@ -1045,7 +1054,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA536: */
/* case BRIDGE_SPCA504B: */
reg_w(dev, 0x31, 0, 0, NULL, 0);
reg_w(gspca_dev, 0x31, 0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
spca504B_PollingDataReady(gspca_dev);
break;

View File

@ -391,7 +391,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
NULL, 0, 500);
return;
}
if (len <= sizeof gspca_dev->usb_buf) {
if (len <= USB_BUF_SZ) {
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),