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
This commit is contained in:
John Baldwin 2014-11-11 18:15:05 +00:00
parent 2da2ade021
commit 858b72dbb8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=274390
4 changed files with 32 additions and 84 deletions

View File

@ -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 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
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);
}

View File

@ -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

View File

@ -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

View File

@ -43,6 +43,7 @@
struct rp_port {
struct tty * rp_tty; /* cross reference */
struct callout rp_timer;
unsigned char state; /* state of dtr */