aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2006-06-25 08:49:12 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:22 -0400
commitcc44a817f65f9b4651643d334f6351b6d1f5e6c2 (patch)
tree818ea9a738b72cfd11f97637312e743aa344e195 /drivers/char
parent45c9b11a1d07770cabb48cb0f7960a77650ffc64 (diff)
[PATCH] fix memory leak in rocketport rp_do_receive
Fix memory leak caused by incorrect use of tty buffer facility. tty buffers are allocated but never processed by call to tty_flip_buffer_push so they accumulate on the full buffer list. Current code uses the buffers as a temporary storage for data before passing it directly to the line discipline. Signed-off-by: Paul Fulghum <paulkf@microgate.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/rocket.c62
1 files changed, 23 insertions, 39 deletions
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 7edc6a4dbdc4..0708c5164c83 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -324,35 +324,15 @@ static void rp_do_receive(struct r_port *info,
324 CHANNEL_t * cp, unsigned int ChanStatus) 324 CHANNEL_t * cp, unsigned int ChanStatus)
325{ 325{
326 unsigned int CharNStat; 326 unsigned int CharNStat;
327 int ToRecv, wRecv, space = 0, count; 327 int ToRecv, wRecv, space;
328 unsigned char *cbuf, *chead; 328 unsigned char *cbuf;
329 char *fbuf, *fhead;
330 struct tty_ldisc *ld;
331
332 ld = tty_ldisc_ref(tty);
333 329
334 ToRecv = sGetRxCnt(cp); 330 ToRecv = sGetRxCnt(cp);
335 space = tty->receive_room;
336 if (space > 2 * TTY_FLIPBUF_SIZE)
337 space = 2 * TTY_FLIPBUF_SIZE;
338 count = 0;
339#ifdef ROCKET_DEBUG_INTR 331#ifdef ROCKET_DEBUG_INTR
340 printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space); 332 printk(KERN_INFO "rp_do_receive(%d)...", ToRecv);
341#endif 333#endif
342 334 if (ToRecv == 0)
343 /* 335 return;
344 * determine how many we can actually read in. If we can't
345 * read any in then we have a software overrun condition.
346 */
347 if (ToRecv > space)
348 ToRecv = space;
349
350 ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
351 if (ToRecv <= 0)
352 goto done;
353
354 cbuf = chead;
355 fbuf = fhead;
356 336
357 /* 337 /*
358 * if status indicates there are errored characters in the 338 * if status indicates there are errored characters in the
@@ -380,6 +360,8 @@ static void rp_do_receive(struct r_port *info,
380 info->read_status_mask); 360 info->read_status_mask);
381#endif 361#endif
382 while (ToRecv) { 362 while (ToRecv) {
363 char flag;
364
383 CharNStat = sInW(sGetTxRxDataIO(cp)); 365 CharNStat = sInW(sGetTxRxDataIO(cp));
384#ifdef ROCKET_DEBUG_RECEIVE 366#ifdef ROCKET_DEBUG_RECEIVE
385 printk(KERN_INFO "%x...", CharNStat); 367 printk(KERN_INFO "%x...", CharNStat);
@@ -392,17 +374,16 @@ static void rp_do_receive(struct r_port *info,
392 } 374 }
393 CharNStat &= info->read_status_mask; 375 CharNStat &= info->read_status_mask;
394 if (CharNStat & STMBREAKH) 376 if (CharNStat & STMBREAKH)
395 *fbuf++ = TTY_BREAK; 377 flag = TTY_BREAK;
396 else if (CharNStat & STMPARITYH) 378 else if (CharNStat & STMPARITYH)
397 *fbuf++ = TTY_PARITY; 379 flag = TTY_PARITY;
398 else if (CharNStat & STMFRAMEH) 380 else if (CharNStat & STMFRAMEH)
399 *fbuf++ = TTY_FRAME; 381 flag = TTY_FRAME;
400 else if (CharNStat & STMRCVROVRH) 382 else if (CharNStat & STMRCVROVRH)
401 *fbuf++ = TTY_OVERRUN; 383 flag = TTY_OVERRUN;
402 else 384 else
403 *fbuf++ = TTY_NORMAL; 385 flag = TTY_NORMAL;
404 *cbuf++ = CharNStat & 0xff; 386 tty_insert_flip_char(tty, CharNStat & 0xff, flag);
405 count++;
406 ToRecv--; 387 ToRecv--;
407 } 388 }
408 389
@@ -422,20 +403,23 @@ static void rp_do_receive(struct r_port *info,
422 * characters at time by doing repeated word IO 403 * characters at time by doing repeated word IO
423 * transfer. 404 * transfer.
424 */ 405 */
406 space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
407 if (space < ToRecv) {
408#ifdef ROCKET_DEBUG_RECEIVE
409 printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
410#endif
411 if (space <= 0)
412 return;
413 ToRecv = space;
414 }
425 wRecv = ToRecv >> 1; 415 wRecv = ToRecv >> 1;
426 if (wRecv) 416 if (wRecv)
427 sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv); 417 sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
428 if (ToRecv & 1) 418 if (ToRecv & 1)
429 cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp)); 419 cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
430 memset(fbuf, TTY_NORMAL, ToRecv);
431 cbuf += ToRecv;
432 fbuf += ToRecv;
433 count += ToRecv;
434 } 420 }
435 /* Push the data up to the tty layer */ 421 /* Push the data up to the tty layer */
436 ld->receive_buf(tty, chead, fhead, count); 422 tty_flip_buffer_push(tty);
437done:
438 tty_ldisc_deref(ld);
439} 423}
440 424
441/* 425/*