diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-18 12:51:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-20 14:19:31 -0500 |
commit | c4a98793a63c423c9e1af51822325969e23c16d4 (patch) | |
tree | 9711b371b6eb6ba1ffa9a8201f3528308526cd00 /drivers/media/video/em28xx | |
parent | 625ff1679456d8adb9af0c980394ea3954e727a8 (diff) |
V4L/DVB (9646): em28xx: avoid allocating/dealocating memory on every control urb
Before this patch, every register setup on em28xx were dynamically
allocating a temporary buffer for control URB's to be handled.
To avoid this ping-pong, use, instead a pre-allocated buffer.
Also, be sure that read control URB's also use the buffer, instead of
relying on a stack buffer.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 48 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 5 |
2 files changed, 31 insertions, 22 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 038da614a734..9551b8ab8c44 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -69,19 +69,29 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, | |||
69 | int ret, byte; | 69 | int ret, byte; |
70 | 70 | ||
71 | if (dev->state & DEV_DISCONNECTED) | 71 | if (dev->state & DEV_DISCONNECTED) |
72 | return(-ENODEV); | 72 | return -ENODEV; |
73 | |||
74 | if (len > URB_MAX_CTRL_SIZE) | ||
75 | return -EINVAL; | ||
73 | 76 | ||
74 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); | 77 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); |
75 | 78 | ||
76 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 79 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
77 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 80 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
78 | 0x0000, reg, buf, len, HZ); | 81 | 0x0000, reg, dev->urb_buf, len, HZ); |
82 | if (ret < 0) { | ||
83 | if (reg_debug) | ||
84 | printk(" failed!\n"); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | if (len) | ||
89 | memcpy(buf, dev->urb_buf, len); | ||
79 | 90 | ||
80 | if (reg_debug) { | 91 | if (reg_debug) { |
81 | printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); | 92 | printk("%02x values: ", ret); |
82 | for (byte = 0; byte < len; byte++) | 93 | for (byte = 0; byte < len; byte++) |
83 | printk(" %02x", (unsigned char)buf[byte]); | 94 | printk(" %02x", (unsigned char)buf[byte]); |
84 | |||
85 | printk("\n"); | 95 | printk("\n"); |
86 | } | 96 | } |
87 | 97 | ||
@@ -104,14 +114,16 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) | |||
104 | 114 | ||
105 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 115 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
106 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 116 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
107 | 0x0000, reg, &val, 1, HZ); | 117 | 0x0000, reg, dev->urb_buf, 1, HZ); |
118 | if (ret < 0) { | ||
119 | printk(" failed!\n"); | ||
120 | return ret; | ||
121 | } | ||
108 | 122 | ||
109 | if (reg_debug) | 123 | val = dev->urb_buf[0]; |
110 | printk(ret < 0 ? " failed!\n" : | ||
111 | "%02x\n", (unsigned char) val); | ||
112 | 124 | ||
113 | if (ret < 0) | 125 | if (reg_debug) |
114 | return ret; | 126 | printk("%02x\n", (unsigned char) val); |
115 | 127 | ||
116 | return val; | 128 | return val; |
117 | } | 129 | } |
@@ -130,19 +142,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
130 | { | 142 | { |
131 | int ret; | 143 | int ret; |
132 | 144 | ||
133 | /*usb_control_msg seems to expect a kmalloced buffer */ | ||
134 | unsigned char *bufs; | ||
135 | |||
136 | if (dev->state & DEV_DISCONNECTED) | 145 | if (dev->state & DEV_DISCONNECTED) |
137 | return -ENODEV; | 146 | return -ENODEV; |
138 | 147 | ||
139 | if (len < 1) | 148 | if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) |
140 | return -EINVAL; | 149 | return -EINVAL; |
141 | 150 | ||
142 | bufs = kmalloc(len, GFP_KERNEL); | ||
143 | |||
144 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); | 151 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); |
145 | |||
146 | if (reg_debug) { | 152 | if (reg_debug) { |
147 | int i; | 153 | int i; |
148 | for (i = 0; i < len; ++i) | 154 | for (i = 0; i < len; ++i) |
@@ -150,16 +156,14 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
150 | printk("\n"); | 156 | printk("\n"); |
151 | } | 157 | } |
152 | 158 | ||
153 | if (!bufs) | 159 | memcpy(dev->urb_buf, buf, len); |
154 | return -ENOMEM; | ||
155 | memcpy(bufs, buf, len); | ||
156 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, | 160 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, |
157 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 161 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
158 | 0x0000, reg, bufs, len, HZ); | 162 | 0x0000, reg, dev->urb_buf, len, HZ); |
163 | |||
159 | if (dev->wait_after_write) | 164 | if (dev->wait_after_write) |
160 | msleep(dev->wait_after_write); | 165 | msleep(dev->wait_after_write); |
161 | 166 | ||
162 | kfree(bufs); | ||
163 | return ret; | 167 | return ret; |
164 | } | 168 | } |
165 | 169 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 82781178e0a3..1adf3d9d9bff 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -102,6 +102,9 @@ | |||
102 | #define EM28XX_MIN_BUF 4 | 102 | #define EM28XX_MIN_BUF 4 |
103 | #define EM28XX_DEF_BUF 8 | 103 | #define EM28XX_DEF_BUF 8 |
104 | 104 | ||
105 | /*Limits the max URB message size */ | ||
106 | #define URB_MAX_CTRL_SIZE 80 | ||
107 | |||
105 | /* Params for validated field */ | 108 | /* Params for validated field */ |
106 | #define EM28XX_BOARD_NOT_VALIDATED 1 | 109 | #define EM28XX_BOARD_NOT_VALIDATED 1 |
107 | #define EM28XX_BOARD_VALIDATED 0 | 110 | #define EM28XX_BOARD_VALIDATED 0 |
@@ -451,6 +454,8 @@ struct em28xx { | |||
451 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | 454 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ |
452 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ | 455 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ |
453 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ | 456 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ |
457 | char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ | ||
458 | |||
454 | /* helper funcs that call usb_control_msg */ | 459 | /* helper funcs that call usb_control_msg */ |
455 | int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, | 460 | int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, |
456 | char *buf, int len); | 461 | char *buf, int len); |