diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-09 03:17:42 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:31 -0500 |
commit | 205260102c5cef4180982eec88aaeb6934faf214 (patch) | |
tree | 51ae649d6776187e20981d18c3cae0a906bd1311 /drivers/media/video/gspca/sq905c.c | |
parent | 6ca3f255f790764f9cfc41d3ac02823d83dfa5ac (diff) |
V4L/DVB (13141): gspca_sq905c: once one frame is discarded it keeps discarding all frames
While checking all gspca sub drivers pkt_scan functions for a bug I found in
1 of them (and after checking also in another), I noticed a bug in the
gspca_sq905c work queue function, once it has decided to start discarding a
frame because the application is not reading fast enough (and thus returning
buffers to fill fast enough), it never stops discarding.
This patch fixes this by simply completely removing the "discarding"
variable, if we need to discard the current frame because there is no buffer
to store it, the "frame" pointer will be NULL, so that is all we need to
check.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/sq905c.c')
-rw-r--r-- | drivers/media/video/gspca/sq905c.c | 23 |
1 files changed, 7 insertions, 16 deletions
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index 91689250543..81020f6f739 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c | |||
@@ -119,7 +119,6 @@ static void sq905c_dostream(struct work_struct *work) | |||
119 | int bytes_left; /* bytes remaining in current frame. */ | 119 | int bytes_left; /* bytes remaining in current frame. */ |
120 | int data_len; /* size to use for the next read. */ | 120 | int data_len; /* size to use for the next read. */ |
121 | int act_len; | 121 | int act_len; |
122 | int discarding = 0; /* true if we failed to get space for frame. */ | ||
123 | int packet_type; | 122 | int packet_type; |
124 | int ret; | 123 | int ret; |
125 | u8 *buffer; | 124 | u8 *buffer; |
@@ -131,8 +130,6 @@ static void sq905c_dostream(struct work_struct *work) | |||
131 | } | 130 | } |
132 | 131 | ||
133 | while (gspca_dev->present && gspca_dev->streaming) { | 132 | while (gspca_dev->present && gspca_dev->streaming) { |
134 | if (!gspca_dev->present) | ||
135 | goto quit_stream; | ||
136 | /* Request the header, which tells the size to download */ | 133 | /* Request the header, which tells the size to download */ |
137 | ret = usb_bulk_msg(gspca_dev->dev, | 134 | ret = usb_bulk_msg(gspca_dev->dev, |
138 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), | 135 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), |
@@ -150,16 +147,12 @@ static void sq905c_dostream(struct work_struct *work) | |||
150 | /* We keep the header. It has other information, too. */ | 147 | /* We keep the header. It has other information, too. */ |
151 | packet_type = FIRST_PACKET; | 148 | packet_type = FIRST_PACKET; |
152 | frame = gspca_get_i_frame(gspca_dev); | 149 | frame = gspca_get_i_frame(gspca_dev); |
153 | if (frame && !discarding) { | 150 | if (frame) |
154 | gspca_frame_add(gspca_dev, packet_type, | 151 | gspca_frame_add(gspca_dev, packet_type, |
155 | frame, buffer, FRAME_HEADER_LEN); | 152 | frame, buffer, FRAME_HEADER_LEN); |
156 | } else | 153 | while (bytes_left > 0 && gspca_dev->present) { |
157 | discarding = 1; | ||
158 | while (bytes_left > 0) { | ||
159 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? | 154 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? |
160 | SQ905C_MAX_TRANSFER : bytes_left; | 155 | SQ905C_MAX_TRANSFER : bytes_left; |
161 | if (!gspca_dev->present) | ||
162 | goto quit_stream; | ||
163 | ret = usb_bulk_msg(gspca_dev->dev, | 156 | ret = usb_bulk_msg(gspca_dev->dev, |
164 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), | 157 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), |
165 | buffer, data_len, &act_len, | 158 | buffer, data_len, &act_len, |
@@ -174,19 +167,17 @@ static void sq905c_dostream(struct work_struct *work) | |||
174 | packet_type = LAST_PACKET; | 167 | packet_type = LAST_PACKET; |
175 | else | 168 | else |
176 | packet_type = INTER_PACKET; | 169 | packet_type = INTER_PACKET; |
177 | frame = gspca_get_i_frame(gspca_dev); | 170 | if (frame) |
178 | if (frame && !discarding) | ||
179 | gspca_frame_add(gspca_dev, packet_type, | 171 | gspca_frame_add(gspca_dev, packet_type, |
180 | frame, buffer, data_len); | 172 | frame, buffer, data_len); |
181 | else | ||
182 | discarding = 1; | ||
183 | } | 173 | } |
184 | } | 174 | } |
185 | quit_stream: | 175 | quit_stream: |
186 | mutex_lock(&gspca_dev->usb_lock); | 176 | if (gspca_dev->present) { |
187 | if (gspca_dev->present) | 177 | mutex_lock(&gspca_dev->usb_lock); |
188 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); | 178 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); |
189 | mutex_unlock(&gspca_dev->usb_lock); | 179 | mutex_unlock(&gspca_dev->usb_lock); |
180 | } | ||
190 | kfree(buffer); | 181 | kfree(buffer); |
191 | } | 182 | } |
192 | 183 | ||