diff options
author | Jarod Wilson <jarod@redhat.com> | 2011-01-14 14:40:32 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-01-19 09:52:21 -0500 |
commit | 559d162e1ebcdb61e89f154f2c2db376af072b0e (patch) | |
tree | 296f29a525809e88d72c6a3b2579128d6396f6b9 /drivers | |
parent | 324b04ba5da7918a2409f8113e46843bfbd89e67 (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')
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr-i2c.c | 30 | ||||
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr.h | 3 |
2 files changed, 16 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 | ||
107 | error: | ||
108 | kfree(buf); | ||
109 | return ret; | 105 | return ret; |
110 | } | 106 | } |
111 | 107 | ||
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 29f74269400c..ee74e3be9a6a 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h | |||
@@ -25,6 +25,7 @@ | |||
25 | KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE) | 25 | KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE) |
26 | 26 | ||
27 | #define HDPVR_MAX 8 | 27 | #define HDPVR_MAX 8 |
28 | #define HDPVR_I2C_MAX_SIZE 128 | ||
28 | 29 | ||
29 | /* Define these values to match your devices */ | 30 | /* Define these values to match your devices */ |
30 | #define HD_PVR_VENDOR_ID 0x2040 | 31 | #define HD_PVR_VENDOR_ID 0x2040 |
@@ -109,6 +110,8 @@ struct hdpvr_device { | |||
109 | struct i2c_adapter i2c_adapter; | 110 | struct i2c_adapter i2c_adapter; |
110 | /* I2C lock */ | 111 | /* I2C lock */ |
111 | struct mutex i2c_mutex; | 112 | struct mutex i2c_mutex; |
113 | /* I2C message buffer space */ | ||
114 | char i2c_buf[HDPVR_I2C_MAX_SIZE]; | ||
112 | 115 | ||
113 | /* For passing data to ir-kbd-i2c */ | 116 | /* For passing data to ir-kbd-i2c */ |
114 | struct IR_i2c_init_data ir_i2c_init_data; | 117 | struct IR_i2c_init_data ir_i2c_init_data; |