summaryrefslogtreecommitdiffstats
path: root/sys/dev/rp
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2004-06-21 13:02:25 +0000
committergallatin <gallatin@FreeBSD.org>2004-06-21 13:02:25 +0000
commitae2a2c5a14cfdb36af5430d18d9599b9a6ed3708 (patch)
treea737038708dca786a51144f0b14283094ff9d8e4 /sys/dev/rp
parent9c97a4d517868b0d384e8ecb927940d8e470fb92 (diff)
downloadFreeBSD-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.c47
-rw-r--r--sys/dev/rp/rp_pci.c13
-rw-r--r--sys/dev/rp/rpreg.h2
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];
OpenPOWER on IntegriCloud