aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/tty_buffer.c85
1 files changed, 65 insertions, 20 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd6778a..91e326ffe7db 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -185,25 +185,19 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
185 /* Should possibly check if this fails for the largest buffer we 185 /* Should possibly check if this fails for the largest buffer we
186 have queued and recycle that ? */ 186 have queued and recycle that ? */
187} 187}
188
189/** 188/**
190 * tty_buffer_request_room - grow tty buffer if needed 189 * __tty_buffer_request_room - grow tty buffer if needed
191 * @tty: tty structure 190 * @tty: tty structure
192 * @size: size desired 191 * @size: size desired
193 * 192 *
194 * Make at least size bytes of linear space available for the tty 193 * Make at least size bytes of linear space available for the tty
195 * buffer. If we fail return the size we managed to find. 194 * buffer. If we fail return the size we managed to find.
196 * 195 * Locking: Caller must hold tty->buf.lock
197 * Locking: Takes tty->buf.lock
198 */ 196 */
199int tty_buffer_request_room(struct tty_struct *tty, size_t size) 197static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
200{ 198{
201 struct tty_buffer *b, *n; 199 struct tty_buffer *b, *n;
202 int left; 200 int left;
203 unsigned long flags;
204
205 spin_lock_irqsave(&tty->buf.lock, flags);
206
207 /* OPTIMISATION: We could keep a per tty "zero" sized buffer to 201 /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
208 remove this conditional if its worth it. This would be invisible 202 remove this conditional if its worth it. This would be invisible
209 to the callers */ 203 to the callers */
@@ -225,9 +219,30 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
225 size = left; 219 size = left;
226 } 220 }
227 221
228 spin_unlock_irqrestore(&tty->buf.lock, flags);
229 return size; 222 return size;
230} 223}
224
225
226/**
227 * tty_buffer_request_room - grow tty buffer if needed
228 * @tty: tty structure
229 * @size: size desired
230 *
231 * Make at least size bytes of linear space available for the tty
232 * buffer. If we fail return the size we managed to find.
233 *
234 * Locking: Takes tty->buf.lock
235 */
236int tty_buffer_request_room(struct tty_struct *tty, size_t size)
237{
238 unsigned long flags;
239 int length;
240
241 spin_lock_irqsave(&tty->buf.lock, flags);
242 length = __tty_buffer_request_room(tty, size);
243 spin_unlock_irqrestore(&tty->buf.lock, flags);
244 return length;
245}
231EXPORT_SYMBOL_GPL(tty_buffer_request_room); 246EXPORT_SYMBOL_GPL(tty_buffer_request_room);
232 247
233/** 248/**
@@ -249,14 +264,22 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
249 int copied = 0; 264 int copied = 0;
250 do { 265 do {
251 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); 266 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
252 int space = tty_buffer_request_room(tty, goal); 267 int space;
253 struct tty_buffer *tb = tty->buf.tail; 268 unsigned long flags;
269 struct tty_buffer *tb;
270
271 spin_lock_irqsave(&tty->buf.lock, flags);
272 space = __tty_buffer_request_room(tty, goal);
273 tb = tty->buf.tail;
254 /* If there is no space then tb may be NULL */ 274 /* If there is no space then tb may be NULL */
255 if (unlikely(space == 0)) 275 if (unlikely(space == 0)) {
276 spin_unlock_irqrestore(&tty->buf.lock, flags);
256 break; 277 break;
278 }
257 memcpy(tb->char_buf_ptr + tb->used, chars, space); 279 memcpy(tb->char_buf_ptr + tb->used, chars, space);
258 memset(tb->flag_buf_ptr + tb->used, flag, space); 280 memset(tb->flag_buf_ptr + tb->used, flag, space);
259 tb->used += space; 281 tb->used += space;
282 spin_unlock_irqrestore(&tty->buf.lock, flags);
260 copied += space; 283 copied += space;
261 chars += space; 284 chars += space;
262 /* There is a small chance that we need to split the data over 285 /* There is a small chance that we need to split the data over
@@ -286,14 +309,22 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
286 int copied = 0; 309 int copied = 0;
287 do { 310 do {
288 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); 311 int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
289 int space = tty_buffer_request_room(tty, goal); 312 int space;
290 struct tty_buffer *tb = tty->buf.tail; 313 unsigned long __flags;
314 struct tty_buffer *tb;
315
316 spin_lock_irqsave(&tty->buf.lock, __flags);
317 space = __tty_buffer_request_room(tty, goal);
318 tb = tty->buf.tail;
291 /* If there is no space then tb may be NULL */ 319 /* If there is no space then tb may be NULL */
292 if (unlikely(space == 0)) 320 if (unlikely(space == 0)) {
321 spin_unlock_irqrestore(&tty->buf.lock, __flags);
293 break; 322 break;
323 }
294 memcpy(tb->char_buf_ptr + tb->used, chars, space); 324 memcpy(tb->char_buf_ptr + tb->used, chars, space);
295 memcpy(tb->flag_buf_ptr + tb->used, flags, space); 325 memcpy(tb->flag_buf_ptr + tb->used, flags, space);
296 tb->used += space; 326 tb->used += space;
327 spin_unlock_irqrestore(&tty->buf.lock, __flags);
297 copied += space; 328 copied += space;
298 chars += space; 329 chars += space;
299 flags += space; 330 flags += space;
@@ -344,13 +375,20 @@ EXPORT_SYMBOL(tty_schedule_flip);
344int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, 375int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
345 size_t size) 376 size_t size)
346{ 377{
347 int space = tty_buffer_request_room(tty, size); 378 int space;
379 unsigned long flags;
380 struct tty_buffer *tb;
381
382 spin_lock_irqsave(&tty->buf.lock, flags);
383 space = __tty_buffer_request_room(tty, size);
384
385 tb = tty->buf.tail;
348 if (likely(space)) { 386 if (likely(space)) {
349 struct tty_buffer *tb = tty->buf.tail;
350 *chars = tb->char_buf_ptr + tb->used; 387 *chars = tb->char_buf_ptr + tb->used;
351 memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); 388 memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
352 tb->used += space; 389 tb->used += space;
353 } 390 }
391 spin_unlock_irqrestore(&tty->buf.lock, flags);
354 return space; 392 return space;
355} 393}
356EXPORT_SYMBOL_GPL(tty_prepare_flip_string); 394EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -374,13 +412,20 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
374int tty_prepare_flip_string_flags(struct tty_struct *tty, 412int tty_prepare_flip_string_flags(struct tty_struct *tty,
375 unsigned char **chars, char **flags, size_t size) 413 unsigned char **chars, char **flags, size_t size)
376{ 414{
377 int space = tty_buffer_request_room(tty, size); 415 int space;
416 unsigned long __flags;
417 struct tty_buffer *tb;
418
419 spin_lock_irqsave(&tty->buf.lock, __flags);
420 space = __tty_buffer_request_room(tty, size);
421
422 tb = tty->buf.tail;
378 if (likely(space)) { 423 if (likely(space)) {
379 struct tty_buffer *tb = tty->buf.tail;
380 *chars = tb->char_buf_ptr + tb->used; 424 *chars = tb->char_buf_ptr + tb->used;
381 *flags = tb->flag_buf_ptr + tb->used; 425 *flags = tb->flag_buf_ptr + tb->used;
382 tb->used += space; 426 tb->used += space;
383 } 427 }
428 spin_unlock_irqrestore(&tty->buf.lock, __flags);
384 return space; 429 return space;
385} 430}
386EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); 431EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);