aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/hdpvr/hdpvr-i2c.c
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2011-01-14 14:40:32 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 09:52:21 -0500
commit559d162e1ebcdb61e89f154f2c2db376af072b0e (patch)
tree296f29a525809e88d72c6a3b2579128d6396f6b9 /drivers/media/video/hdpvr/hdpvr-i2c.c
parent324b04ba5da7918a2409f8113e46843bfbd89e67 (diff)
[media] hdpvr: reduce latency of i2c read/write w/recycled buffer
The current hdpvr code kmalloc's a new buffer for every i2c read and write. Rather than do that, lets allocate a buffer in the driver's device struct and just use that every time. The size I've chosen for the buffer is the maximum size I could ascertain might be used by either ir-kbd-i2c or lirc_zilog, plus a bit of padding (lirc_zilog may use up to 100 bytes on tx, rounded that up to 128). Note that this might also remedy user reports of very sluggish behavior of IR receive with hdpvr hardware. v2: make sure (len <= (dev->i2c_buf)) [Jean Delvare] Reported-by: Jean Delvare <khali@linux-fr.org> Acked-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/hdpvr/hdpvr-i2c.c')
-rw-r--r--drivers/media/video/hdpvr/hdpvr-i2c.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
index 45b88cf60d68..89b71faeaac2 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -57,23 +57,21 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
57 unsigned char addr, char *data, int len) 57 unsigned char addr, char *data, int len)
58{ 58{
59 int ret; 59 int ret;
60 char *buf = kmalloc(len, GFP_KERNEL); 60
61 if (!buf) 61 if (len > sizeof(dev->i2c_buf))
62 return -ENOMEM; 62 return -EINVAL;
63 63
64 ret = usb_control_msg(dev->udev, 64 ret = usb_control_msg(dev->udev,
65 usb_rcvctrlpipe(dev->udev, 0), 65 usb_rcvctrlpipe(dev->udev, 0),
66 REQTYPE_I2C_READ, CTRL_READ_REQUEST, 66 REQTYPE_I2C_READ, CTRL_READ_REQUEST,
67 (bus << 8) | addr, 0, buf, len, 1000); 67 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
68 68
69 if (ret == len) { 69 if (ret == len) {
70 memcpy(data, buf, len); 70 memcpy(data, &dev->i2c_buf, len);
71 ret = 0; 71 ret = 0;
72 } else if (ret >= 0) 72 } else if (ret >= 0)
73 ret = -EIO; 73 ret = -EIO;
74 74
75 kfree(buf);
76
77 return ret; 75 return ret;
78} 76}
79 77
@@ -81,31 +79,29 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
81 unsigned char addr, char *data, int len) 79 unsigned char addr, char *data, int len)
82{ 80{
83 int ret; 81 int ret;
84 char *buf = kmalloc(len, GFP_KERNEL);
85 if (!buf)
86 return -ENOMEM;
87 82
88 memcpy(buf, data, len); 83 if (len > sizeof(dev->i2c_buf))
84 return -EINVAL;
85
86 memcpy(&dev->i2c_buf, data, len);
89 ret = usb_control_msg(dev->udev, 87 ret = usb_control_msg(dev->udev,
90 usb_sndctrlpipe(dev->udev, 0), 88 usb_sndctrlpipe(dev->udev, 0),
91 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, 89 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
92 (bus << 8) | addr, 0, buf, len, 1000); 90 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
93 91
94 if (ret < 0) 92 if (ret < 0)
95 goto error; 93 return ret;
96 94
97 ret = usb_control_msg(dev->udev, 95 ret = usb_control_msg(dev->udev,
98 usb_rcvctrlpipe(dev->udev, 0), 96 usb_rcvctrlpipe(dev->udev, 0),
99 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, 97 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
100 0, 0, buf, 2, 1000); 98 0, 0, &dev->i2c_buf, 2, 1000);
101 99
102 if ((ret == 2) && (buf[1] == (len - 1))) 100 if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
103 ret = 0; 101 ret = 0;
104 else if (ret >= 0) 102 else if (ret >= 0)
105 ret = -EIO; 103 ret = -EIO;
106 104
107error:
108 kfree(buf);
109 return ret; 105 return ret;
110} 106}
111 107