diff options
author | gallatin <gallatin@FreeBSD.org> | 2004-06-21 13:02:25 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2004-06-21 13:02:25 +0000 |
commit | ae2a2c5a14cfdb36af5430d18d9599b9a6ed3708 (patch) | |
tree | a737038708dca786a51144f0b14283094ff9d8e4 /sys/dev/rp | |
parent | 9c97a4d517868b0d384e8ecb927940d8e470fb92 (diff) | |
download | FreeBSD-src-ae2a2c5a14cfdb36af5430d18d9599b9a6ed3708.zip FreeBSD-src-ae2a2c5a14cfdb36af5430d18d9599b9a6ed3708.tar.gz |
Prevent the rp driver from panic'ing on first access and make at
least the pci device unloadable
- Use ttymalloc() rather than a plain malloc to allocate the
rp->rp_tty ttys. This is now required due to the recent locking
changes to ttys and prevents a panic due to locking an unitialized
t_mtx.
- Allow the pci driver to be unloaded. This involved moving
the call rp_releaseresource() to the end of rp_pcireleaseresource(),
since rp_pcireleaseresource() uses ctlp->dev, which is freed
by rp_releaseresource().
- Allow the generic part of the driver to be unattached by providing
a hook to cancel timeouts.
Glanced at by: obrien
Diffstat (limited to 'sys/dev/rp')
-rw-r--r-- | sys/dev/rp/rp.c | 47 | ||||
-rw-r--r-- | sys/dev/rp/rp_pci.c | 13 | ||||
-rw-r--r-- | sys/dev/rp/rpreg.h | 2 |
3 files changed, 33 insertions, 29 deletions
diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c index 3c092f5..1219ef5 100644 --- a/sys/dev/rp/rp.c +++ b/sys/dev/rp/rp.c @@ -565,6 +565,7 @@ void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) **********************************************************************/ static timeout_t rpdtrwakeup; +struct callout_handle rp_callout_handle; static d_open_t rpopen; static d_close_t rpclose; @@ -789,7 +790,8 @@ static void rp_do_poll(void *not_used) } } if(rp_num_ports_open) - timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); + rp_callout_handle = timeout(rp_do_poll, + (void *)NULL, POLL_INTERVAL); } int @@ -801,7 +803,6 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) int ChanStatus, line, i, count; int retval; struct rp_port *rp; - struct tty *tty; struct cdev **dev_nodes; unit = device_get_unit(ctlp->dev); @@ -809,9 +810,10 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) printf("RocketPort%d (Version %s) %d ports.\n", unit, RocketPortVersion, num_ports); rp_num_ports[unit] = num_ports; + callout_handle_init(&rp_callout_handle); ctlp->rp = rp = (struct rp_port *) - malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); + malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); if (rp == NULL) { device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); retval = ENOMEM; @@ -823,15 +825,6 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) minor_to_unit[i] = unit; bzero(rp, sizeof(struct rp_port) * num_ports); - ctlp->tty = tty = (struct tty *) - malloc(sizeof(struct tty) * num_ports, M_TTYS, - M_NOWAIT | M_ZERO); - if(tty == NULL) { - device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n"); - retval = ENOMEM; - goto nogo; - } - oldspl = spltty(); rp_addr(unit) = rp; splx(oldspl); @@ -867,15 +860,15 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) port = 0; for(aiop=0; aiop < num_aiops; aiop++) { num_chan = sGetAiopNumChan(ctlp, aiop); - for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { - rp->rp_tty = tty; + for(chan=0; chan < num_chan; chan++, port++, rp++) { + rp->rp_tty = ttymalloc(NULL); rp->rp_port = port; rp->rp_ctlp = ctlp; rp->rp_unit = unit; rp->rp_chan = chan; rp->rp_aiop = aiop; - tty->t_line = 0; + rp->rp_tty->t_line = 0; /* tty->t_termios = deftermios; */ rp->dtr_wait = 3 * hz; @@ -920,8 +913,19 @@ void rp_releaseresource(CONTROLLER_t *ctlp) { int i, s, unit; + struct rp_port *rp; + unit = device_get_unit(ctlp->dev); + if (rp_addr(unit) != NULL) { + for (i = 0; i < rp_num_ports[unit]; i++) { + rp = rp_addr(unit) + i; + s = ttyrel(rp->rp_tty); + if (s) { + printf("Detaching with active tty (%d refs)!\n", s); + } + } + } if (ctlp->rp != NULL) { s = spltty(); @@ -935,10 +939,6 @@ rp_releaseresource(CONTROLLER_t *ctlp) free(ctlp->rp, M_DEVBUF); ctlp->rp = NULL; } - if (ctlp->tty != NULL) { - free(ctlp->tty, M_DEVBUF); - ctlp->tty = NULL; - } if (ctlp->dev != NULL) { for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++) destroy_dev(ctlp->dev_nodes[i]); @@ -947,6 +947,11 @@ rp_releaseresource(CONTROLLER_t *ctlp) } } +void +rp_untimeout(void) +{ + untimeout(rp_do_poll, (void *)NULL, rp_callout_handle); +} static int rpopen(dev, flag, mode, td) struct cdev *dev; @@ -1072,8 +1077,8 @@ open_top: } if(rp_num_ports_open == 1) - timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); - + rp_callout_handle = timeout(rp_do_poll, + (void *)NULL, POLL_INTERVAL); } if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && diff --git a/sys/dev/rp/rp_pci.c b/sys/dev/rp/rp_pci.c index ca7494b..70aaa5b 100644 --- a/sys/dev/rp/rp_pci.c +++ b/sys/dev/rp/rp_pci.c @@ -208,7 +208,6 @@ nogo: return (retval); } -#if notdef static int rp_pcidetach(device_t dev) { @@ -238,20 +237,22 @@ rp_pcishutdown(device_t dev) return (0); } -#endif /* notdef */ static void rp_pcireleaseresource(CONTROLLER_t *ctlp) { - rp_releaseresource(ctlp); - + rp_untimeout(); if (ctlp->io != NULL) { if (ctlp->io[0] != NULL) bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[0], ctlp->io[0]); free(ctlp->io, M_DEVBUF); + ctlp->io = NULL; } - if (ctlp->io_rid != NULL) + if (ctlp->io_rid != NULL) { free(ctlp->io_rid, M_DEVBUF); + ctlp->io = NULL; + } + rp_releaseresource(ctlp); } static int @@ -351,10 +352,8 @@ static device_method_t rp_pcimethods[] = { /* Device interface */ DEVMETHOD(device_probe, rp_pciprobe), DEVMETHOD(device_attach, rp_pciattach), -#if notdef DEVMETHOD(device_detach, rp_pcidetach), DEVMETHOD(device_shutdown, rp_pcishutdown), -#endif /* notdef */ { 0, 0 } }; diff --git a/sys/dev/rp/rpreg.h b/sys/dev/rp/rpreg.h index 6852f7c..1122ace 100644 --- a/sys/dev/rp/rpreg.h +++ b/sys/dev/rp/rpreg.h @@ -368,7 +368,6 @@ struct CONTROLLER_str struct resource **io; /* IO resources */ struct rp_port *rp; /* port */ - struct tty *tty; /* tty */ /* Device nodes */ struct cdev **dev_nodes; @@ -1005,6 +1004,7 @@ void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags); void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags); int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports); void rp_releaseresource(CONTROLLER_t *ctlp); +void rp_untimeout(void); #ifndef ROCKET_C extern Byte_t R[RDATASIZE]; |