Re: serial module oops

Ion Badulescu (ionut@moisil.wal.rhno.columbia.edu)
Thu, 12 Dec 1996 23:53:50 -0500 (EST)


On Thu, 12 Dec 1996, Matthew Harrell wrote:

> When I load the serial module and do a "setserial <device> spd_vhi" on the
> port I get the following oops
>
> divide error: 0000
> CPU: 0
> EIP: 0010:[<c282a38d>]
> EFLAGS: 00010082
> eax: fffffffe ebx: fffffffe ecx: 00000000 edx: ffffffff
> esi: c0080de0 edi: 000009f1 ebp: 00000000 esp: c1cd5f08
> ds: 0018 es: 0018 ss: 0018
> Process setserial (pid: 129, process nr: 17, stackpage=c1cd5000)
> Stack: c1cf0000 00000086 c1cd5f34 c1cf0000 00000000 c01899c7 c1cf0000 00000000
> c0080de0 c1ac033c c282ba04 c1ca0c0c c1cf0934 c282a230 c1cf0000 00000000
> c1cf0000 00000001 c1ff3c40 00000000 00000001 00000246 c01817eb c1cf0000
> Call Trace: [<c01899c7>] [<c282ba04>] [<c282a230>] [<c01817eb>] [<c0181d02>] [<c01233d8>] [<c01234dc>]
> [<c010a8d8>]
> Code: f7 7e 10 89 c3 b9 05 00 00 00 31 d2 f7 f1 89 c3 85 db 75 05

Yup, same here, the function is actually rs_wait_until_sent.

Actually, there are two problems in the new serial driver:

1. trying to configure an inexistent port results in a "Divide error"
oops;

2. the autoconfig code will fail if the driver is not a module

Patch follows (as usual :)

Ionut

--
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

--- linux-2.1.15/drivers/char/serial.c.old Thu Dec 12 23:20:48 1996 +++ linux-2.1.15/drivers/char/serial.c Thu Dec 12 23:46:41 1996 @@ -2365,6 +2365,9 @@ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) return; + if (info->state->type == PORT_UNKNOWN) + return; + orig_jiffies = jiffies; /* * Set the check interval to be 1/5 of the estimated time to @@ -2817,9 +2820,6 @@ info->port = state->port; info->flags = state->flags; - if(check_region(info->port,8)) - return; /* Area in use */ - save_flags(flags); cli(); /* @@ -3102,6 +3102,12 @@ state->irq = req->irq; state->port = req->port; state->flags = req->flags; + + if(check_region(state->port,8)) { + restore_flags(flags); + printk("register_serial(): I/O region in use\n"); + return -1; /* Area in use */ + } autoconfig(state); if (state->type == PORT_UNKNOWN) { restore_flags(flags);