Commit d8d1721c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'media/v4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:
 "A series of fixup patches meant to fix the usage of DMA on stack, plus
  one warning fixup"

* tag 'media/v4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (32 commits)
  [media] radio-bcm2048: don't ignore errors
  [media] pctv452e: fix semicolon.cocci warnings
  [media] flexcop-usb: don't use stack for DMA
  [media] stk-webcam: don't use stack for DMA
  [media] s2255drv: don't use stack for DMA
  [media] cpia2_usb: don't use stack for DMA
  [media] digitv: handle error code on RC query
  [media] dw2102: return error if su3000_power_ctrl() fails
  [media] nova-t-usb2: handle error code on RC query
  [media] technisat-usb2: use DMA buffers for I2C transfers
  [media] pctv452e: don't call BUG_ON() on non-fatal error
  [media] pctv452e: don't do DMA on stack
  [media] nova-t-usb2: don't do DMA on stack
  [media] gp8psk: don't go past the buffer size
  [media] gp8psk: don't do DMA on stack
  [media] dtv5100: don't do DMA on stack
  [media] dtt200u: handle USB control message errors
  [media] dtt200u: don't do DMA on stack
  [media] dtt200u-fe: handle errors on USB control messages
  [media] dtt200u-fe: don't do DMA on stack
  ...
parents 41e6410e 1aeb5b61
......@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
(read ? 0x80 : 0);
int ret;
mutex_lock(&fc_usb->data_mutex);
if (!read)
memcpy(fc_usb->data, val, sizeof(*val));
int len = usb_control_msg(fc_usb->udev,
ret = usb_control_msg(fc_usb->udev,
read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
request,
request_type, /* 0xc0 read or 0x40 write */
wAddress,
0,
val,
fc_usb->data,
sizeof(u32),
B2C2_WAIT_FOR_OPERATION_RDW * HZ);
if (len != sizeof(u32)) {
if (ret != sizeof(u32)) {
err("error while %s dword from %d (%d).", read ? "reading" :
"writing", wAddress, wRegOffsPCI);
return -EIO;
if (ret >= 0)
ret = -EIO;
}
return 0;
if (read && ret >= 0)
memcpy(val, fc_usb->data, sizeof(*val));
mutex_unlock(&fc_usb->data_mutex);
return ret;
}
/*
* DKT 010817 - add support for V8 memory read/write and flash update
......@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
{
u8 request_type = USB_TYPE_VENDOR;
u16 wIndex;
int nWaitTime, pipe, len;
int nWaitTime, pipe, ret;
wIndex = page << 8;
if (buflen > sizeof(fc_usb->data)) {
err("Buffer size bigger than max URB control message\n");
return -EIO;
}
switch (req) {
case B2C2_USB_READ_V8_MEM:
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
......@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
wAddress, wIndex, buflen);
len = usb_control_msg(fc_usb->udev, pipe,
mutex_lock(&fc_usb->data_mutex);
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
memcpy(fc_usb->data, pbBuffer, buflen);
ret = usb_control_msg(fc_usb->udev, pipe,
req,
request_type,
wAddress,
wIndex,
pbBuffer,
fc_usb->data,
buflen,
nWaitTime * HZ);
if (ret != buflen)
ret = -EIO;
if (ret >= 0) {
ret = 0;
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
memcpy(pbBuffer, fc_usb->data, buflen);
}
debug_dump(pbBuffer, len, deb_v8);
return len == buflen ? 0 : -EIO;
mutex_unlock(&fc_usb->data_mutex);
debug_dump(pbBuffer, ret, deb_v8);
return ret;
}
#define bytes_left_to_read_on_page(paddr,buflen) \
......@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
fc->dvb_adapter.proposed_mac, 6);
}
#if 0
static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
u16 buflen, u8 *pvBuffer)
{
u16 wValue;
u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
int nWaitTime = 2,
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
wValue = (func << 8) | extra;
len = usb_control_msg(fc_usb->udev,pipe,
B2C2_USB_UTILITY,
request_type,
wValue,
wIndex,
pvBuffer,
buflen,
nWaitTime * HZ);
return len == buflen ? 0 : -EIO;
}
#endif
/* usb i2c stuff */
static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
......@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
{
struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
u16 wValue, wIndex;
int nWaitTime,pipe,len;
int nWaitTime, pipe, ret;
u8 request_type = USB_TYPE_VENDOR;
if (buflen > sizeof(fc_usb->data)) {
err("Buffer size bigger than max URB control message\n");
return -EIO;
}
switch (func) {
case USB_FUNC_I2C_WRITE:
case USB_FUNC_I2C_MULTIWRITE:
......@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
wValue & 0xff, wValue >> 8,
wIndex & 0xff, wIndex >> 8);
len = usb_control_msg(fc_usb->udev,pipe,
mutex_lock(&fc_usb->data_mutex);
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
memcpy(fc_usb->data, buf, buflen);
ret = usb_control_msg(fc_usb->udev, pipe,
req,
request_type,
wValue,
wIndex,
buf,
fc_usb->data,
buflen,
nWaitTime * HZ);
return len == buflen ? 0 : -EREMOTEIO;
if (ret != buflen)
ret = -EIO;
if (ret >= 0) {
ret = 0;
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
memcpy(buf, fc_usb->data, buflen);
}
mutex_unlock(&fc_usb->data_mutex);
return 0;
}
/* actual bus specific access functions,
......@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
/* general flexcop init */
fc_usb = fc->bus_specific;
fc_usb->fc_dev = fc;
mutex_init(&fc_usb->data_mutex);
fc->read_ibi_reg = flexcop_usb_read_ibi_reg;
fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
......
......@@ -29,6 +29,10 @@ struct flexcop_usb {
u8 tmp_buffer[1023+190];
int tmp_buffer_length;
/* for URB control messages */
u8 data[80];
struct mutex data_mutex;
};
#if 0
......
......@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)
static int write_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
unsigned char *buf;
int ret;
if (!registers || size <= 0)
return -EINVAL;
return usb_control_msg(udev,
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, registers, size);
ret = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
buf, /* buffer */
size,
HZ);
kfree(buf);
return ret;
}
/****************************************************************************
......@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,
static int read_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
unsigned char *buf;
int ret;
if (!registers || size <= 0)
return -EINVAL;
return usb_control_msg(udev,
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
request,
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
buf, /* buffer */
size,
HZ);
if (ret >= 0)
memcpy(registers, buf, size);
kfree(buf);
return ret;
}
/******************************************************************************
......
......@@ -52,17 +52,16 @@ u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
struct af9005_device_state {
u8 sequence;
int led_state;
unsigned char data[256];
struct mutex data_mutex;
};
static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
int readwrite, int type, u8 * values, int len)
{
struct af9005_device_state *st = d->priv;
u8 obuf[16] = { 0 };
u8 ibuf[17] = { 0 };
u8 command;
int i;
int ret;
u8 command, seq;
int i, ret;
if (len < 1) {
err("generic read/write, less than 1 byte. Makes no sense.");
......@@ -73,16 +72,17 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
return -EINVAL;
}
obuf[0] = 14; /* rest of buffer length low */
obuf[1] = 0; /* rest of buffer length high */
mutex_lock(&st->data_mutex);
st->data[0] = 14; /* rest of buffer length low */
st->data[1] = 0; /* rest of buffer length high */
obuf[2] = AF9005_REGISTER_RW; /* register operation */
obuf[3] = 12; /* rest of buffer length */
st->data[2] = AF9005_REGISTER_RW; /* register operation */
st->data[3] = 12; /* rest of buffer length */
obuf[4] = st->sequence++; /* sequence number */
st->data[4] = seq = st->sequence++; /* sequence number */
obuf[5] = (u8) (reg >> 8); /* register address */
obuf[6] = (u8) (reg & 0xff);
st->data[5] = (u8) (reg >> 8); /* register address */
st->data[6] = (u8) (reg & 0xff);
if (type == AF9005_OFDM_REG) {
command = AF9005_CMD_OFDM_REG;
......@@ -96,51 +96,52 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
command |= readwrite;
if (readwrite == AF9005_CMD_WRITE)
for (i = 0; i < len; i++)
obuf[8 + i] = values[i];
st->data[8 + i] = values[i];
else if (type == AF9005_TUNER_REG)
/* read command for tuner, the first byte contains the i2c address */
obuf[8] = values[0];
obuf[7] = command;
st->data[8] = values[0];
st->data[7] = command;
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 17, 0);
if (ret)
return ret;
goto ret;
/* sanity check */
if (ibuf[2] != AF9005_REGISTER_RW_ACK) {
if (st->data[2] != AF9005_REGISTER_RW_ACK) {
err("generic read/write, wrong reply code.");
return -EIO;
ret = -EIO;
goto ret;
}
if (ibuf[3] != 0x0d) {
if (st->data[3] != 0x0d) {
err("generic read/write, wrong length in reply.");
return -EIO;
ret = -EIO;
goto ret;
}
if (ibuf[4] != obuf[4]) {
if (st->data[4] != seq) {
err("generic read/write, wrong sequence in reply.");
return -EIO;
ret = -EIO;
goto ret;
}
/*
Windows driver doesn't check these fields, in fact sometimes
the register in the reply is different that what has been sent
if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) {
err("generic read/write, wrong register in reply.");
return -EIO;
}
if (ibuf[7] != command) {
err("generic read/write wrong command in reply.");
return -EIO;
}
* In thesis, both input and output buffers should have
* identical values for st->data[5] to st->data[8].
* However, windows driver doesn't check these fields, in fact
* sometimes the register in the reply is different that what
* has been sent
*/
if (ibuf[16] != 0x01) {
if (st->data[16] != 0x01) {
err("generic read/write wrong status code in reply.");
return -EIO;
ret = -EIO;
goto ret;
}
if (readwrite == AF9005_CMD_READ)
for (i = 0; i < len; i++)
values[i] = ibuf[8 + i];
values[i] = st->data[8 + i];
return 0;
ret:
mutex_unlock(&st->data_mutex);
return ret;
}
......@@ -464,8 +465,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
struct af9005_device_state *st = d->priv;
int ret, i, packet_len;
u8 buf[64];
u8 ibuf[64];
u8 seq;
if (wlen < 0) {
err("send command, wlen less than 0 bytes. Makes no sense.");
......@@ -480,94 +480,97 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
return -EINVAL;
}
packet_len = wlen + 5;
buf[0] = (u8) (packet_len & 0xff);
buf[1] = (u8) ((packet_len & 0xff00) >> 8);
buf[2] = 0x26; /* packet type */
buf[3] = wlen + 3;
buf[4] = st->sequence++;
buf[5] = command;
buf[6] = wlen;
mutex_lock(&st->data_mutex);
st->data[0] = (u8) (packet_len & 0xff);
st->data[1] = (u8) ((packet_len & 0xff00) >> 8);
st->data[2] = 0x26; /* packet type */
st->data[3] = wlen + 3;
st->data[4] = seq = st->sequence++;
st->data[5] = command;
st->data[6] = wlen;
for (i = 0; i < wlen; i++)
buf[7 + i] = wbuf[i];
ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
if (ret)
return ret;
if (ibuf[2] != 0x27) {
st->data[7 + i] = wbuf[i];
ret = dvb_usb_generic_rw(d, st->data, wlen + 7, st->data, rlen + 7, 0);
if (st->data[2] != 0x27) {
err("send command, wrong reply code.");
return -EIO;
}
if (ibuf[4] != buf[4]) {
ret = -EIO;
} else if (st->data[4] != seq) {
err("send command, wrong sequence in reply.");
return -EIO;
}
if (ibuf[5] != 0x01) {
ret = -EIO;
} else if (st->data[5] != 0x01) {
err("send command, wrong status code in reply.");
return -EIO;
}
if (ibuf[6] != rlen) {
ret = -EIO;
} else if (st->data[6] != rlen) {
err("send command, invalid data length in reply.");
return -EIO;
ret = -EIO;
}
for (i = 0; i < rlen; i++)
rbuf[i] = ibuf[i + 7];
return 0;
if (!ret) {
for (i = 0; i < rlen; i++)
rbuf[i] = st->data[i + 7];
}
mutex_unlock(&st->data_mutex);
return ret;
}
int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
int len)
{
struct af9005_device_state *st = d->priv;
u8 obuf[16], ibuf[14];
u8 seq;
int ret, i;
memset(obuf, 0, sizeof(obuf));
memset(ibuf, 0, sizeof(ibuf));
mutex_lock(&st->data_mutex);
obuf[0] = 14; /* length of rest of packet low */
obuf[1] = 0; /* length of rest of packer high */
memset(st->data, 0, sizeof(st->data));
obuf[2] = 0x2a; /* read/write eeprom */
st->data[0] = 14; /* length of rest of packet low */
st->data[1] = 0; /* length of rest of packer high */
obuf[3] = 12; /* size */
st->data[2] = 0x2a; /* read/write eeprom */
obuf[4] = st->sequence++;
st->data[3] = 12; /* size */
obuf[5] = 0; /* read */
st->data[4] = seq = st->sequence++;
obuf[6] = len;
obuf[7] = address;
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
if (ret)
return ret;
if (ibuf[2] != 0x2b) {
st->data[5] = 0; /* read */
st->data[6] = len;
st->data[7] = address;
ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 14, 0);
if (st->data[2] != 0x2b) {
err("Read eeprom, invalid reply code");
return -EIO;
}
if (ibuf[3] != 10) {
ret = -EIO;
} else if (st->data[3] != 10) {
err("Read eeprom, invalid reply length");
return -EIO;
}
if (ibuf[4] != obuf[4]) {
ret = -EIO;
} else if (st->data[4] != seq) {
err("Read eeprom, wrong sequence in reply ");
return -EIO;
}
if (ibuf[5] != 1) {
ret = -EIO;
} else if (st->data[5] != 1) {
err("Read eeprom, wrong status in reply ");
return -EIO;
ret = -EIO;
}
for (i = 0; i < len; i++) {
values[i] = ibuf[6 + i];
if (!ret) {
for (i = 0; i < len; i++)
values[i] = st->data[6 + i];
}
return 0;
mutex_unlock(&st->data_mutex);
return ret;
}
static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply,
u8 *buf, int size)
{
u8 buf[FW_BULKOUT_SIZE + 2];
u16 checksum;
int act_len, i, ret;
memset(buf, 0, sizeof(buf));
memset(buf, 0, size);
buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
switch (type) {
......@@ -720,15 +723,21 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
{
int i, packets, ret, act_len;
u8 buf[FW_BULKOUT_SIZE + 2];
u8 *buf;
u8 reply;
ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf,
FW_BULKOUT_SIZE + 2);
if (ret)
return ret;
goto err;
if (reply != 0x01) {
err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
return -EIO;
ret = -EIO;
goto err;
}
packets = fw->size / FW_BULKOUT_SIZE;
buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
......@@ -743,28 +752,35 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
if (ret) {
err("firmware download failed at packet %d with code %d", i, ret);
return ret;
goto err;
}
}
ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);
ret = af9005_boot_packet(udev, FW_CONFIRM, &reply,
buf, FW_BULKOUT_SIZE + 2);
if (ret)
return ret;
goto err;
if (reply != (u8) (packets & 0xff)) {
err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
return -EIO;
ret = -EIO;
goto err;
}
ret = af9005_boot_packet(udev, FW_BOOT, &reply);
ret = af9005_boot_packet(udev, FW_BOOT, &reply, buf,
FW_BULKOUT_SIZE + 2);
if (ret)
return ret;
ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
goto err;