Skip to content

Commit

Permalink
[PATCH] fix memory leak in rocketport rp_do_receive
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Fulghum authored and Linus Torvalds committed Jun 25, 2006
1 parent 45c9b11 commit cc44a81
Showing 1 changed file with 23 additions and 39 deletions.
62 changes: 23 additions & 39 deletions drivers/char/rocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,35 +324,15 @@ static void rp_do_receive(struct r_port *info,
CHANNEL_t * cp, unsigned int ChanStatus)
{
unsigned int CharNStat;
int ToRecv, wRecv, space = 0, count;
unsigned char *cbuf, *chead;
char *fbuf, *fhead;
struct tty_ldisc *ld;

ld = tty_ldisc_ref(tty);
int ToRecv, wRecv, space;
unsigned char *cbuf;

ToRecv = sGetRxCnt(cp);
space = tty->receive_room;
if (space > 2 * TTY_FLIPBUF_SIZE)
space = 2 * TTY_FLIPBUF_SIZE;
count = 0;
#ifdef ROCKET_DEBUG_INTR
printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
printk(KERN_INFO "rp_do_receive(%d)...", ToRecv);
#endif

/*
* determine how many we can actually read in. If we can't
* read any in then we have a software overrun condition.
*/
if (ToRecv > space)
ToRecv = space;

ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
if (ToRecv <= 0)
goto done;

cbuf = chead;
fbuf = fhead;
if (ToRecv == 0)
return;

/*
* if status indicates there are errored characters in the
Expand Down Expand Up @@ -380,6 +360,8 @@ static void rp_do_receive(struct r_port *info,
info->read_status_mask);
#endif
while (ToRecv) {
char flag;

CharNStat = sInW(sGetTxRxDataIO(cp));
#ifdef ROCKET_DEBUG_RECEIVE
printk(KERN_INFO "%x...", CharNStat);
Expand All @@ -392,17 +374,16 @@ static void rp_do_receive(struct r_port *info,
}
CharNStat &= info->read_status_mask;
if (CharNStat & STMBREAKH)
*fbuf++ = TTY_BREAK;
flag = TTY_BREAK;
else if (CharNStat & STMPARITYH)
*fbuf++ = TTY_PARITY;
flag = TTY_PARITY;
else if (CharNStat & STMFRAMEH)
*fbuf++ = TTY_FRAME;
flag = TTY_FRAME;
else if (CharNStat & STMRCVROVRH)
*fbuf++ = TTY_OVERRUN;
flag = TTY_OVERRUN;
else
*fbuf++ = TTY_NORMAL;
*cbuf++ = CharNStat & 0xff;
count++;
flag = TTY_NORMAL;
tty_insert_flip_char(tty, CharNStat & 0xff, flag);
ToRecv--;
}

Expand All @@ -422,20 +403,23 @@ static void rp_do_receive(struct r_port *info,
* characters at time by doing repeated word IO
* transfer.
*/
space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
if (space < ToRecv) {
#ifdef ROCKET_DEBUG_RECEIVE
printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
#endif
if (space <= 0)
return;
ToRecv = space;
}
wRecv = ToRecv >> 1;
if (wRecv)
sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
if (ToRecv & 1)
cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
memset(fbuf, TTY_NORMAL, ToRecv);
cbuf += ToRecv;
fbuf += ToRecv;
count += ToRecv;
}
/* Push the data up to the tty layer */
ld->receive_buf(tty, chead, fhead, count);
done:
tty_ldisc_deref(ld);
tty_flip_buffer_push(tty);
}

/*
Expand Down

0 comments on commit cc44a81

Please sign in to comment.