summaryrefslogtreecommitdiffstats
path: root/sys/dev/rp
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-11-11 18:15:05 +0000
committerjhb <jhb@FreeBSD.org>2014-11-11 18:15:05 +0000
commit1929b21119d6af0991d957701f166768e0f49d0a (patch)
tree9674138805b23cf14d9e594fb2e24b9e332fde07 /sys/dev/rp
parent2326e023197afa75bb7c543bc94c11fcbe7cc4f6 (diff)
downloadFreeBSD-src-1929b21119d6af0991d957701f166768e0f49d0a.zip
FreeBSD-src-1929b21119d6af0991d957701f166768e0f49d0a.tar.gz
Use the callout(9) API instead of timeout(9). To do this more cleanly,
convert a global timer to a per-controller timer. This works much better with locking and removes the need for several global lookup tables. Tested by: ambrisko
Diffstat (limited to 'sys/dev/rp')
-rw-r--r--sys/dev/rp/rp.c106
-rw-r--r--sys/dev/rp/rp_pci.c3
-rw-r--r--sys/dev/rp/rpreg.h6
-rw-r--r--sys/dev/rp/rpvar.h1
4 files changed, 32 insertions, 84 deletions
diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c
index 520ca80..5027694 100644
--- a/sys/dev/rp/rp.c
+++ b/sys/dev/rp/rp.c
@@ -552,24 +552,12 @@ void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
Begin FreeBsd-specific driver code
**********************************************************************/
-struct callout_handle rp_callout_handle;
-
-static int rp_num_ports_open = 0;
-static int rp_ndevs = 0;
-
-static int rp_num_ports[4]; /* Number of ports on each controller */
-
-#define POLL_INTERVAL 1
+#define POLL_INTERVAL (hz / 100)
#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
-static struct rp_port *p_rp_addr[4];
-static struct rp_port *p_rp_table[MAX_RP_PORTS];
-#define rp_addr(unit) (p_rp_addr[unit])
-#define rp_table(port) (p_rp_table[port])
-
/*
* The top-level routines begin here
*/
@@ -676,46 +664,31 @@ static void rp_handle_port(struct rp_port *rp)
*/
}
-static void rp_do_poll(void *not_used)
+static void rp_do_poll(void *arg)
{
CONTROLLER_t *ctl;
struct rp_port *rp;
struct tty *tp;
- int unit, aiop, ch, line, count;
+ int count;
unsigned char CtlMask, AiopMask;
- for(unit = 0; unit < rp_ndevs; unit++) {
- rp = rp_addr(unit);
+ rp = arg;
+ tp = rp->rp_tty;
+ tty_lock_assert(tp, MA_OWNED);
ctl = rp->rp_ctlp;
CtlMask = ctl->ctlmask(ctl);
- for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
- if(CtlMask & 1) {
- AiopMask = sGetAiopIntStatus(ctl, aiop);
- for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
- if(AiopMask & 1) {
- line = (unit << 5) | (aiop << 3) | ch;
- rp = rp_table(line);
- rp_handle_port(rp);
- }
- }
+ if (CtlMask & (1 << rp->rp_aiop)) {
+ AiopMask = sGetAiopIntStatus(ctl, rp->rp_aiop);
+ if (AiopMask & (1 << rp->rp_chan)) {
+ rp_handle_port(rp);
}
}
- for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
- line++, rp++) {
- tp = rp->rp_tty;
- tty_lock(tp);
- count = sGetTxCnt(&rp->rp_channel);
- if (count >= 0 &&
- (count <= rp->rp_restart)) {
- rpstart(tp);
- }
- tty_unlock(tp);
+ count = sGetTxCnt(&rp->rp_channel);
+ if (count >= 0 && (count <= rp->rp_restart)) {
+ rpstart(tp);
}
- }
- if(rp_num_ports_open)
- rp_callout_handle = timeout(rp_do_poll,
- (void *)NULL, POLL_INTERVAL);
+ callout_schedule(&rp->rp_timer, POLL_INTERVAL);
}
static struct ttydevsw rp_tty_class = {
@@ -745,7 +718,7 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
int unit;
int num_chan;
int aiop, chan, port;
- int ChanStatus, line, count;
+ int ChanStatus;
int retval;
struct rp_port *rp;
struct tty *tp;
@@ -754,9 +727,8 @@ 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->num_ports = num_ports;
ctlp->rp = rp = (struct rp_port *)
malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO);
if (rp == NULL) {
@@ -765,16 +737,12 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
goto nogo;
}
- count = unit * 32; /* board times max ports per card SG */
-
- bzero(rp, sizeof(struct rp_port) * num_ports);
- rp_addr(unit) = rp;
-
port = 0;
for(aiop=0; aiop < num_aiops; aiop++) {
num_chan = sGetAiopNumChan(ctlp, aiop);
for(chan=0; chan < num_chan; chan++, port++, rp++) {
rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp);
+ callout_init_mtx(&rp->rp_timer, tty_getlock(tp), 0);
rp->rp_port = port;
rp->rp_ctlp = ctlp;
rp->rp_unit = unit;
@@ -794,13 +762,10 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
}
ChanStatus = sGetChanStatus(&rp->rp_channel);
rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
- line = (unit << 5) | (aiop << 3) | chan;
- rp_table(line) = rp;
tty_makedev(tp, NULL, "R%r%r", unit, port);
}
}
- rp_ndevs++;
mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF);
ctlp->hwmtx_init = 1;
return (0);
@@ -814,40 +779,26 @@ nogo:
void
rp_releaseresource(CONTROLLER_t *ctlp)
{
- int i, unit;
struct rp_port *rp;
+ int i;
-
- 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;
+ if (ctlp->rp != NULL) {
+ for (i = 0; i < ctlp->num_ports; i++) {
+ rp = ctlp->rp + i;
atomic_add_32(&ctlp->free, 1);
tty_lock(rp->rp_tty);
tty_rel_gone(rp->rp_tty);
}
+ free(ctlp->rp, M_DEVBUF);
+ ctlp->rp = NULL;
}
while (ctlp->free != 0) {
pause("rpwt", hz / 10);
}
- if (ctlp->rp != NULL) {
- for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
- if (p_rp_addr[i] == ctlp->rp)
- p_rp_addr[i] = NULL;
- for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
- if (p_rp_table[i] == ctlp->rp)
- p_rp_table[i] = NULL;
- free(ctlp->rp, M_DEVBUF);
- ctlp->rp = NULL;
- }
-}
-
-void
-rp_untimeout(void)
-{
- untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
+ if (ctlp->hwmtx_init)
+ mtx_destroy(&ctlp->hwmtx);
}
static int
@@ -893,15 +844,11 @@ rpopen(struct tty *tp)
sSetRTS(&rp->rp_channel);
*/
- rp_num_ports_open++;
-
IntMask = sGetChanIntID(&rp->rp_channel);
IntMask = IntMask & rp->rp_intmask;
ChanStatus = sGetChanStatus(&rp->rp_channel);
- if(rp_num_ports_open == 1)
- rp_callout_handle = timeout(rp_do_poll,
- (void *)NULL, POLL_INTERVAL);
+ callout_reset(&rp->rp_timer, POLL_INTERVAL, rp_do_poll, rp);
device_busy(rp->rp_ctlp->dev);
return(0);
@@ -913,6 +860,7 @@ rpclose(struct tty *tp)
struct rp_port *rp;
rp = tty_softc(tp);
+ callout_stop(&rp->rp_timer);
rphardclose(tp);
device_unbusy(rp->rp_ctlp->dev);
}
diff --git a/sys/dev/rp/rp_pci.c b/sys/dev/rp/rp_pci.c
index e7b9832..3479ab7 100644
--- a/sys/dev/rp/rp_pci.c
+++ b/sys/dev/rp/rp_pci.c
@@ -237,7 +237,7 @@ rp_pcishutdown(device_t dev)
static void
rp_pcireleaseresource(CONTROLLER_t *ctlp)
{
- rp_untimeout();
+ rp_releaseresource(ctlp);
if (ctlp->io != NULL) {
if (ctlp->io[0] != NULL)
bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[0], ctlp->io[0]);
@@ -248,7 +248,6 @@ rp_pcireleaseresource(CONTROLLER_t *ctlp)
free(ctlp->io_rid, M_DEVBUF);
ctlp->io = NULL;
}
- rp_releaseresource(ctlp);
}
static int
diff --git a/sys/dev/rp/rpreg.h b/sys/dev/rp/rpreg.h
index c8960eb..c5a8cac 100644
--- a/sys/dev/rp/rpreg.h
+++ b/sys/dev/rp/rpreg.h
@@ -364,6 +364,7 @@ struct CONTROLLER_str
struct mtx hwmtx; /* Spinlock protecting hardware. */
int hwmtx_init;
int free;
+ int num_ports;
/* Device and resource management */
device_t dev; /* device */
@@ -1008,18 +1009,17 @@ 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);
static __inline void
rp_lock(CONTROLLER_T *CtlP)
{
if (CtlP->hwmtx_init != 0)
- mtx_lock_spin(&CtlP->hwmtx);
+ mtx_lock(&CtlP->hwmtx);
}
static __inline void
rp_unlock(CONTROLLER_T *CtlP)
{
if (CtlP->hwmtx_init != 0)
- mtx_unlock_spin(&CtlP->hwmtx);
+ mtx_unlock(&CtlP->hwmtx);
}
#ifndef ROCKET_C
diff --git a/sys/dev/rp/rpvar.h b/sys/dev/rp/rpvar.h
index f7f28aa..fd5faf3 100644
--- a/sys/dev/rp/rpvar.h
+++ b/sys/dev/rp/rpvar.h
@@ -43,6 +43,7 @@
struct rp_port {
struct tty * rp_tty; /* cross reference */
+ struct callout rp_timer;
unsigned char state; /* state of dtr */
OpenPOWER on IntegriCloud